Merge ~cjwatson/launchpad:rename-slave-store into launchpad:master
- Git
- lp:~cjwatson/launchpad
- rename-slave-store
- Merge into master
Proposed by
Colin Watson
Status: | Merged |
---|---|
Approved by: | Colin Watson |
Approved revision: | e7f8ce7f6fa1fbacf82a518ce805e4720d4fc63e |
Merge reported by: | Otto Co-Pilot |
Merged at revision: | not available |
Proposed branch: | ~cjwatson/launchpad:rename-slave-store |
Merge into: | launchpad:master |
Diff against target: |
1495 lines (+201/-197) 47 files modified
cronscripts/librarian-feed-swift.py (+3/-3) cronscripts/translations-export-to-branch.py (+1/-1) lib/lp/app/stories/basics/xx-dbpolicy.txt (+32/-29) lib/lp/bugs/scripts/bugtasktargetnamecaches.py (+2/-2) lib/lp/buildmaster/model/builder.py (+2/-2) lib/lp/code/model/branchcloud.py (+3/-3) lib/lp/code/model/tests/test_branchcloud.py (+3/-2) lib/lp/registry/scripts/teamparticipation.py (+3/-3) lib/lp/services/database/doc/db-policy.txt (+2/-2) lib/lp/services/database/doc/storm-store-reset.txt (+1/-1) lib/lp/services/database/doc/storm.txt (+17/-17) lib/lp/services/database/interfaces.py (+2/-2) lib/lp/services/database/policy.py (+2/-2) lib/lp/services/database/tests/test_bulk.py (+9/-9) lib/lp/services/database/transaction_policy.py (+2/-2) lib/lp/services/librarian/tests/test_client.py (+2/-2) lib/lp/services/librarianserver/swift.py (+3/-3) lib/lp/services/oauth/model.py (+1/-1) lib/lp/services/session/adapters.py (+4/-4) lib/lp/services/session/configure.zcml (+1/-1) lib/lp/services/session/tests/test_session.py (+2/-2) lib/lp/services/webapp/adapter.py (+3/-3) lib/lp/services/webapp/batching.py (+2/-2) lib/lp/services/webapp/database.zcml (+2/-2) lib/lp/services/webapp/doc/test_adapter_permissions.txt (+1/-1) lib/lp/services/webapp/publication.py (+1/-1) lib/lp/services/webapp/tests/test_dbpolicy.py (+47/-47) lib/lp/services/worlddata/model/language.py (+2/-2) lib/lp/soyuz/model/archive.py (+2/-2) lib/lp/soyuz/tests/test_archive.py (+1/-1) lib/lp/testing/factory.py (+1/-1) lib/lp/translations/doc/poexport-request.txt (+1/-1) lib/lp/translations/doc/poexportqueue-replication-lag.txt (+2/-2) lib/lp/translations/doc/potmsgset.txt (+1/-1) lib/lp/translations/interfaces/poexportrequest.py (+1/-1) lib/lp/translations/interfaces/potmsgset.py (+2/-2) lib/lp/translations/model/poexportrequest.py (+7/-7) lib/lp/translations/model/potmsgset.py (+1/-1) lib/lp/translations/model/translationgroup.py (+3/-3) lib/lp/translations/model/translationimportqueue.py (+5/-5) lib/lp/translations/model/vpoexport.py (+1/-1) lib/lp/translations/scripts/tests/test_translations_to_branch.py (+4/-4) lib/lp/translations/scripts/translations_to_branch.py (+2/-2) lib/lp/translations/tests/test_autoapproval.py (+2/-2) lib/lp/translations/tests/test_translationimportqueue.py (+6/-6) scripts/get-stacked-on-branches.py (+2/-2) utilities/soyuz-sampledata-setup.py (+2/-2) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jürgen Gmach | Approve | ||
Review via email: mp+414253@code.launchpad.net |
Commit message
Rename ISlaveStore to IStandbyStore
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/cronscripts/librarian-feed-swift.py b/cronscripts/librarian-feed-swift.py | |||
2 | index ae60177..1cb1374 100755 | |||
3 | --- a/cronscripts/librarian-feed-swift.py | |||
4 | +++ b/cronscripts/librarian-feed-swift.py | |||
5 | @@ -11,7 +11,7 @@ import os | |||
6 | 11 | 11 | ||
7 | 12 | import six | 12 | import six |
8 | 13 | 13 | ||
10 | 14 | from lp.services.database.interfaces import ISlaveStore | 14 | from lp.services.database.interfaces import IStandbyStore |
11 | 15 | from lp.services.librarian.model import LibraryFileContent | 15 | from lp.services.librarian.model import LibraryFileContent |
12 | 16 | from lp.services.librarianserver import swift | 16 | from lp.services.librarianserver import swift |
13 | 17 | from lp.services.scripts.base import LaunchpadCronScript | 17 | from lp.services.scripts.base import LaunchpadCronScript |
14 | @@ -75,14 +75,14 @@ class LibrarianFeedSwift(LaunchpadCronScript): | |||
15 | 75 | remove = None | 75 | remove = None |
16 | 76 | 76 | ||
17 | 77 | if self.options.start_since: | 77 | if self.options.start_since: |
19 | 78 | self.options.start = ISlaveStore(LibraryFileContent).execute(""" | 78 | self.options.start = IStandbyStore(LibraryFileContent).execute(""" |
20 | 79 | SELECT MAX(id) FROM LibraryFileContent | 79 | SELECT MAX(id) FROM LibraryFileContent |
21 | 80 | WHERE datecreated < current_timestamp at time zone 'UTC' | 80 | WHERE datecreated < current_timestamp at time zone 'UTC' |
22 | 81 | - CAST(%s AS INTERVAL) | 81 | - CAST(%s AS INTERVAL) |
23 | 82 | """, (six.text_type(self.options.start_since),)).get_one()[0] | 82 | """, (six.text_type(self.options.start_since),)).get_one()[0] |
24 | 83 | 83 | ||
25 | 84 | if self.options.end_at: | 84 | if self.options.end_at: |
27 | 85 | self.options.end = ISlaveStore(LibraryFileContent).execute(""" | 85 | self.options.end = IStandbyStore(LibraryFileContent).execute(""" |
28 | 86 | SELECT MAX(id) FROM LibraryFileContent | 86 | SELECT MAX(id) FROM LibraryFileContent |
29 | 87 | WHERE datecreated < current_timestamp at time zone 'UTC' | 87 | WHERE datecreated < current_timestamp at time zone 'UTC' |
30 | 88 | - CAST(%s AS INTERVAL) | 88 | - CAST(%s AS INTERVAL) |
31 | diff --git a/cronscripts/translations-export-to-branch.py b/cronscripts/translations-export-to-branch.py | |||
32 | index 308c693..ca5d1dd 100755 | |||
33 | --- a/cronscripts/translations-export-to-branch.py | |||
34 | +++ b/cronscripts/translations-export-to-branch.py | |||
35 | @@ -10,7 +10,7 @@ access hosted branches. | |||
36 | 10 | 10 | ||
37 | 11 | Besides committing to branches, the script updates Branch records in the | 11 | Besides committing to branches, the script updates Branch records in the |
38 | 12 | database, to let the branch scanner know that the branches' contents | 12 | database, to let the branch scanner know that the branches' contents |
40 | 13 | have been updated. For the rest, the script talks to the slave store. | 13 | have been updated. For the rest, the script talks to the standby store. |
41 | 14 | """ | 14 | """ |
42 | 15 | 15 | ||
43 | 16 | __all__ = [] | 16 | __all__ = [] |
44 | diff --git a/lib/lp/app/stories/basics/xx-dbpolicy.txt b/lib/lp/app/stories/basics/xx-dbpolicy.txt | |||
45 | index b0b8e21..c4ffa89 100644 | |||
46 | --- a/lib/lp/app/stories/basics/xx-dbpolicy.txt | |||
47 | +++ b/lib/lp/app/stories/basics/xx-dbpolicy.txt | |||
48 | @@ -4,11 +4,11 @@ Application Server Database Policy | |||
49 | 4 | The database policy chooses the default Storm store to used. Its goal | 4 | The database policy chooses the default Storm store to used. Its goal |
50 | 5 | is to distribute load away from the master databases to read only | 5 | is to distribute load away from the master databases to read only |
51 | 6 | stores where possible. It will benefit old code - new code should | 6 | stores where possible. It will benefit old code - new code should |
53 | 7 | explicitly select objects from the master or slave stores as needed. | 7 | explicitly select objects from the master or standby stores as needed. |
54 | 8 | 8 | ||
56 | 9 | To test this policy, lets point the MAIN SLAVE store to a Launchpad | 9 | To test this policy, lets point the MAIN STANDBY store to a Launchpad |
57 | 10 | database with a different name. This makes it easy to check if a | 10 | database with a different name. This makes it easy to check if a |
59 | 11 | request is querying the master or slave database. | 11 | request is querying the master or standby database. |
60 | 12 | 12 | ||
61 | 13 | >>> from lp.services.config import config | 13 | >>> from lp.services.config import config |
62 | 14 | >>> from textwrap import dedent | 14 | >>> from textwrap import dedent |
63 | @@ -19,21 +19,24 @@ request is querying the master or slave database. | |||
64 | 19 | >>> config.push('empty_standby', config_overlay) | 19 | >>> config.push('empty_standby', config_overlay) |
65 | 20 | 20 | ||
66 | 21 | >>> from lp.registry.model.person import Person | 21 | >>> from lp.registry.model.person import Person |
68 | 22 | >>> from lp.services.database.interfaces import IMasterStore, ISlaveStore | 22 | >>> from lp.services.database.interfaces import ( |
69 | 23 | ... IMasterStore, | ||
70 | 24 | ... IStandbyStore, | ||
71 | 25 | ... ) | ||
72 | 23 | >>> from lp.testing.layers import DatabaseLayer | 26 | >>> from lp.testing.layers import DatabaseLayer |
73 | 24 | >>> master = IMasterStore(Person) | 27 | >>> master = IMasterStore(Person) |
74 | 25 | >>> dbname = DatabaseLayer._db_fixture.dbname | 28 | >>> dbname = DatabaseLayer._db_fixture.dbname |
75 | 26 | >>> dbname == master.execute("SELECT current_database()").get_one()[0] | 29 | >>> dbname == master.execute("SELECT current_database()").get_one()[0] |
76 | 27 | True | 30 | True |
79 | 28 | >>> slave = ISlaveStore(Person) | 31 | >>> standby = IStandbyStore(Person) |
80 | 29 | >>> print(slave.execute("SELECT current_database()").get_one()[0]) | 32 | >>> print(standby.execute("SELECT current_database()").get_one()[0]) |
81 | 30 | launchpad_empty | 33 | launchpad_empty |
82 | 31 | 34 | ||
83 | 32 | We should confirm that the empty database is as empty as we hope it is. | 35 | We should confirm that the empty database is as empty as we hope it is. |
84 | 33 | 36 | ||
86 | 34 | >>> slave_store = ISlaveStore(Person) | 37 | >>> standby_store = IStandbyStore(Person) |
87 | 35 | >>> master_store = IMasterStore(Person) | 38 | >>> master_store = IMasterStore(Person) |
89 | 36 | >>> slave_store.find(Person).is_empty() | 39 | >>> standby_store.find(Person).is_empty() |
90 | 37 | True | 40 | True |
91 | 38 | >>> master_store.find(Person).is_empty() | 41 | >>> master_store.find(Person).is_empty() |
92 | 39 | False | 42 | False |
93 | @@ -46,16 +49,16 @@ needs to be created externally to this pagetest). | |||
94 | 46 | ... if dbname == DatabaseLayer._db_fixture.dbname: | 49 | ... if dbname == DatabaseLayer._db_fixture.dbname: |
95 | 47 | ... return 'MASTER' | 50 | ... return 'MASTER' |
96 | 48 | ... elif dbname == 'launchpad_empty': | 51 | ... elif dbname == 'launchpad_empty': |
98 | 49 | ... return 'SLAVE' | 52 | ... return 'STANDBY' |
99 | 50 | ... else: | 53 | ... else: |
100 | 51 | ... return 'UNKNOWN' | 54 | ... return 'UNKNOWN' |
101 | 52 | 55 | ||
103 | 53 | Read only requests such as GET and HEAD will use the MAIN SLAVE | 56 | Read only requests such as GET and HEAD will use the MAIN STANDBY |
104 | 54 | Store by default. | 57 | Store by default. |
105 | 55 | 58 | ||
106 | 56 | >>> browser.open('http://launchpad.test/+whichdb') | 59 | >>> browser.open('http://launchpad.test/+whichdb') |
107 | 57 | >>> print(whichdb(browser)) | 60 | >>> print(whichdb(browser)) |
109 | 58 | SLAVE | 61 | STANDBY |
110 | 59 | 62 | ||
111 | 60 | POST requests might make updates, so they use the MAIN MASTER | 63 | POST requests might make updates, so they use the MAIN MASTER |
112 | 61 | Store by default. | 64 | Store by default. |
113 | @@ -66,18 +69,18 @@ Store by default. | |||
114 | 66 | 69 | ||
115 | 67 | This is an unauthenticated browser. These typically have no session, unless | 70 | This is an unauthenticated browser. These typically have no session, unless |
116 | 68 | special dispensation has been made. Without a session, subsequent requests | 71 | special dispensation has been made. Without a session, subsequent requests |
118 | 69 | will then immediately return to using the SLAVE. | 72 | will then immediately return to using the STANDBY. |
119 | 70 | 73 | ||
120 | 71 | >>> browser.open('http://launchpad.test/+whichdb') | 74 | >>> browser.open('http://launchpad.test/+whichdb') |
121 | 72 | >>> print(whichdb(browser)) | 75 | >>> print(whichdb(browser)) |
123 | 73 | SLAVE | 76 | STANDBY |
124 | 74 | 77 | ||
125 | 75 | However, if the request has a session (that is, is authenticated; or is | 78 | However, if the request has a session (that is, is authenticated; or is |
126 | 76 | unauthenticated, but under special dispensation to have a session), once a | 79 | unauthenticated, but under special dispensation to have a session), once a |
127 | 77 | POST request has been made, further GET and HEAD requests from the same client | 80 | POST request has been made, further GET and HEAD requests from the same client |
128 | 78 | continue to use the MAIN MASTER Store by default for 5 minutes. This ensures | 81 | continue to use the MAIN MASTER Store by default for 5 minutes. This ensures |
129 | 79 | that a user will see any changes they have made immediately, even though the | 82 | that a user will see any changes they have made immediately, even though the |
131 | 80 | slave databases may lag some time behind the master database. | 83 | standby databases may lag some time behind the master database. |
132 | 81 | 84 | ||
133 | 82 | >>> browser.addHeader('Authorization', 'Basic mark@example.com:test') | 85 | >>> browser.addHeader('Authorization', 'Basic mark@example.com:test') |
134 | 83 | >>> browser.getControl('Do Post').click() # POST request | 86 | >>> browser.getControl('Do Post').click() # POST request |
135 | @@ -88,19 +91,19 @@ slave databases may lag some time behind the master database. | |||
136 | 88 | MASTER | 91 | MASTER |
137 | 89 | 92 | ||
138 | 90 | GET and HEAD requests from other clients are unaffected though | 93 | GET and HEAD requests from other clients are unaffected though |
140 | 91 | and use the MAIN SLAVE Store by default. | 94 | and use the MAIN STANDBY Store by default. |
141 | 92 | 95 | ||
142 | 93 | >>> anon_browser.open('http://launchpad.test/+whichdb') | 96 | >>> anon_browser.open('http://launchpad.test/+whichdb') |
143 | 94 | >>> print(whichdb(anon_browser)) | 97 | >>> print(whichdb(anon_browser)) |
145 | 95 | SLAVE | 98 | STANDBY |
146 | 96 | >>> admin_browser.open('http://launchpad.test/+whichdb') | 99 | >>> admin_browser.open('http://launchpad.test/+whichdb') |
147 | 97 | >>> print(whichdb(admin_browser)) | 100 | >>> print(whichdb(admin_browser)) |
149 | 98 | SLAVE | 101 | STANDBY |
150 | 99 | 102 | ||
151 | 100 | If no more POST requests are made for 5 minutes, GET and HEAD | 103 | If no more POST requests are made for 5 minutes, GET and HEAD |
153 | 101 | requests will once again be using the MAIN SLAVE store as we | 104 | requests will once again be using the MAIN STANDBY store as we |
154 | 102 | can assume that any changes made to the master database have | 105 | can assume that any changes made to the master database have |
156 | 103 | propagated to the slaves. | 106 | propagated to the standbys. |
157 | 104 | 107 | ||
158 | 105 | To test this, first we need to wind forward the database policy's clock. | 108 | To test this, first we need to wind forward the database policy's clock. |
159 | 106 | 109 | ||
160 | @@ -119,18 +122,18 @@ To test this, first we need to wind forward the database policy's clock. | |||
161 | 119 | 122 | ||
162 | 120 | >>> browser.open('http://launchpad.test/+whichdb') | 123 | >>> browser.open('http://launchpad.test/+whichdb') |
163 | 121 | >>> print(whichdb(browser)) | 124 | >>> print(whichdb(browser)) |
165 | 122 | SLAVE | 125 | STANDBY |
166 | 123 | 126 | ||
167 | 124 | >>> dbpolicy._now = _original_now # Reset the time machine. | 127 | >>> dbpolicy._now = _original_now # Reset the time machine. |
168 | 125 | 128 | ||
169 | 126 | 129 | ||
171 | 127 | When lag gets too bad, we stop using slave databases. This stops | 130 | When lag gets too bad, we stop using standby databases. This stops |
172 | 128 | replication oddities from becoming too bad, as well as lightening the load | 131 | replication oddities from becoming too bad, as well as lightening the load |
174 | 129 | on the slaves allowing them to catch up. | 132 | on the standbys allowing them to catch up. |
175 | 130 | 133 | ||
176 | 131 | >>> anon_browser.open('http://launchpad.test/+whichdb') | 134 | >>> anon_browser.open('http://launchpad.test/+whichdb') |
177 | 132 | >>> print(whichdb(anon_browser)) | 135 | >>> print(whichdb(anon_browser)) |
179 | 133 | SLAVE | 136 | STANDBY |
180 | 134 | 137 | ||
181 | 135 | >>> dbpolicy._test_lag = timedelta(minutes=10) | 138 | >>> dbpolicy._test_lag = timedelta(minutes=10) |
182 | 136 | >>> anon_browser.open('http://launchpad.test/+whichdb') | 139 | >>> anon_browser.open('http://launchpad.test/+whichdb') |
183 | @@ -139,7 +142,7 @@ on the slaves allowing them to catch up. | |||
184 | 139 | >>> dbpolicy._test_lag = None | 142 | >>> dbpolicy._test_lag = None |
185 | 140 | 143 | ||
186 | 141 | 144 | ||
188 | 142 | A 404 error page is shown when code raises a LookupError. If a slave | 145 | A 404 error page is shown when code raises a LookupError. If a standby |
189 | 143 | database is being used, this might have been caused by replication lag | 146 | database is being used, this might have been caused by replication lag |
190 | 144 | if the missing data was only recently created. To fix this surprising | 147 | if the missing data was only recently created. To fix this surprising |
191 | 145 | error, requests are always retried using the master database before | 148 | error, requests are always retried using the master database before |
192 | @@ -148,12 +151,12 @@ returning a 404 error to the user. | |||
193 | 148 | >>> anon_browser.handleErrors = True | 151 | >>> anon_browser.handleErrors = True |
194 | 149 | >>> anon_browser.raiseHttpErrors = False | 152 | >>> anon_browser.raiseHttpErrors = False |
195 | 150 | 153 | ||
197 | 151 | # Confirm requests are going to the SLAVE | 154 | # Confirm requests are going to the STANDBY |
198 | 152 | >>> anon_browser.open('http://launchpad.test/+whichdb') | 155 | >>> anon_browser.open('http://launchpad.test/+whichdb') |
199 | 153 | >>> print(whichdb(anon_browser)) | 156 | >>> print(whichdb(anon_browser)) |
201 | 154 | SLAVE | 157 | STANDBY |
202 | 155 | 158 | ||
204 | 156 | # The slave database contains no data, but we don't get | 159 | # The standby database contains no data, but we don't get |
205 | 157 | # a 404 page - the request is retried against the MASTER. | 160 | # a 404 page - the request is retried against the MASTER. |
206 | 158 | >>> anon_browser.open('http://launchpad.test/~stub') | 161 | >>> anon_browser.open('http://launchpad.test/~stub') |
207 | 159 | >>> anon_browser.headers['Status'] | 162 | >>> anon_browser.headers['Status'] |
208 | @@ -165,10 +168,10 @@ returning a 404 error to the user. | |||
209 | 165 | >>> anon_browser.headers['Status'] | 168 | >>> anon_browser.headers['Status'] |
210 | 166 | '404 Not Found' | 169 | '404 Not Found' |
211 | 167 | 170 | ||
213 | 168 | # This session is still using the SLAVE though by default. | 171 | # This session is still using the STANDBY though by default. |
214 | 169 | >>> anon_browser.open('http://launchpad.test/+whichdb') | 172 | >>> anon_browser.open('http://launchpad.test/+whichdb') |
215 | 170 | >>> print(whichdb(anon_browser)) | 173 | >>> print(whichdb(anon_browser)) |
217 | 171 | SLAVE | 174 | STANDBY |
218 | 172 | 175 | ||
219 | 173 | Reset our config to avoid affecting other tests. | 176 | Reset our config to avoid affecting other tests. |
220 | 174 | 177 | ||
221 | diff --git a/lib/lp/bugs/scripts/bugtasktargetnamecaches.py b/lib/lp/bugs/scripts/bugtasktargetnamecaches.py | |||
222 | index d6cc18d..3d741fc 100644 | |||
223 | --- a/lib/lp/bugs/scripts/bugtasktargetnamecaches.py | |||
224 | +++ b/lib/lp/bugs/scripts/bugtasktargetnamecaches.py | |||
225 | @@ -21,7 +21,7 @@ from lp.registry.model.productseries import ProductSeries | |||
226 | 21 | from lp.registry.model.sourcepackagename import SourcePackageName | 21 | from lp.registry.model.sourcepackagename import SourcePackageName |
227 | 22 | from lp.services.database.interfaces import ( | 22 | from lp.services.database.interfaces import ( |
228 | 23 | IMasterStore, | 23 | IMasterStore, |
230 | 24 | ISlaveStore, | 24 | IStandbyStore, |
231 | 25 | ) | 25 | ) |
232 | 26 | from lp.services.looptuner import ( | 26 | from lp.services.looptuner import ( |
233 | 27 | ITunableLoop, | 27 | ITunableLoop, |
234 | @@ -62,7 +62,7 @@ class BugTaskTargetNameCachesTunableLoop: | |||
235 | 62 | Returns a list of (target, set_of_cached_names) pairs, where target is | 62 | Returns a list of (target, set_of_cached_names) pairs, where target is |
236 | 63 | a tuple of IDs from the columns in target_columns. | 63 | a tuple of IDs from the columns in target_columns. |
237 | 64 | """ | 64 | """ |
239 | 65 | store = ISlaveStore(BugTask) | 65 | store = IStandbyStore(BugTask) |
240 | 66 | candidate_set = store.find(target_columns).config(distinct=True) | 66 | candidate_set = store.find(target_columns).config(distinct=True) |
241 | 67 | candidates = defaultdict(set) | 67 | candidates = defaultdict(set) |
242 | 68 | for candidate in candidate_set: | 68 | for candidate in candidate_set: |
243 | diff --git a/lib/lp/buildmaster/model/builder.py b/lib/lp/buildmaster/model/builder.py | |||
244 | index eeef109..1fd92ec 100644 | |||
245 | --- a/lib/lp/buildmaster/model/builder.py | |||
246 | +++ b/lib/lp/buildmaster/model/builder.py | |||
247 | @@ -50,7 +50,7 @@ from lp.services.database.constants import UTC_NOW | |||
248 | 50 | from lp.services.database.decoratedresultset import DecoratedResultSet | 50 | from lp.services.database.decoratedresultset import DecoratedResultSet |
249 | 51 | from lp.services.database.enumcol import DBEnum | 51 | from lp.services.database.enumcol import DBEnum |
250 | 52 | from lp.services.database.interfaces import ( | 52 | from lp.services.database.interfaces import ( |
252 | 53 | ISlaveStore, | 53 | IStandbyStore, |
253 | 54 | IStore, | 54 | IStore, |
254 | 55 | ) | 55 | ) |
255 | 56 | from lp.services.database.stormbase import StormBase | 56 | from lp.services.database.stormbase import StormBase |
256 | @@ -300,7 +300,7 @@ class BuilderSet: | |||
257 | 300 | 300 | ||
258 | 301 | def getBuildQueueSizes(self): | 301 | def getBuildQueueSizes(self): |
259 | 302 | """See `IBuilderSet`.""" | 302 | """See `IBuilderSet`.""" |
261 | 303 | results = ISlaveStore(BuildQueue).find(( | 303 | results = IStandbyStore(BuildQueue).find(( |
262 | 304 | Count(), | 304 | Count(), |
263 | 305 | Sum(BuildQueue.estimated_duration), | 305 | Sum(BuildQueue.estimated_duration), |
264 | 306 | Processor, | 306 | Processor, |
265 | diff --git a/lib/lp/code/model/branchcloud.py b/lib/lp/code/model/branchcloud.py | |||
266 | index e6969f3..000a1ad 100644 | |||
267 | --- a/lib/lp/code/model/branchcloud.py | |||
268 | +++ b/lib/lp/code/model/branchcloud.py | |||
269 | @@ -29,7 +29,7 @@ from zope.interface import provider | |||
270 | 29 | from lp.code.interfaces.branch import IBranchCloud | 29 | from lp.code.interfaces.branch import IBranchCloud |
271 | 30 | from lp.code.model.revision import RevisionCache | 30 | from lp.code.model.revision import RevisionCache |
272 | 31 | from lp.registry.model.product import Product | 31 | from lp.registry.model.product import Product |
274 | 32 | from lp.services.database.interfaces import ISlaveStore | 32 | from lp.services.database.interfaces import IStandbyStore |
275 | 33 | 33 | ||
276 | 34 | 34 | ||
277 | 35 | @provider(IBranchCloud) | 35 | @provider(IBranchCloud) |
278 | @@ -44,8 +44,8 @@ class BranchCloud: | |||
279 | 44 | commits = Alias(Count(RevisionCache.revision_id)) | 44 | commits = Alias(Count(RevisionCache.revision_id)) |
280 | 45 | epoch = datetime.now(pytz.UTC) - timedelta(days=30) | 45 | epoch = datetime.now(pytz.UTC) - timedelta(days=30) |
281 | 46 | # It doesn't matter if this query is even a whole day out of date, so | 46 | # It doesn't matter if this query is even a whole day out of date, so |
284 | 47 | # use the slave store. | 47 | # use the standby store. |
285 | 48 | result = ISlaveStore(RevisionCache).find( | 48 | result = IStandbyStore(RevisionCache).find( |
286 | 49 | (Product.name, | 49 | (Product.name, |
287 | 50 | commits, | 50 | commits, |
288 | 51 | Count(distinct_revision_author), | 51 | Count(distinct_revision_author), |
289 | diff --git a/lib/lp/code/model/tests/test_branchcloud.py b/lib/lp/code/model/tests/test_branchcloud.py | |||
290 | index 4fb7143..2af246f 100644 | |||
291 | --- a/lib/lp/code/model/tests/test_branchcloud.py | |||
292 | +++ b/lib/lp/code/model/tests/test_branchcloud.py | |||
293 | @@ -37,8 +37,9 @@ class TestBranchCloud(TestCaseWithFactory): | |||
294 | 37 | 37 | ||
295 | 38 | def getProductsWithInfo(self, num_products=None): | 38 | def getProductsWithInfo(self, num_products=None): |
296 | 39 | """Get product cloud information.""" | 39 | """Get product cloud information.""" |
299 | 40 | # Since we use the slave store to get the information, we need to | 40 | # Since we use the standby store to get the information, we need to |
300 | 41 | # commit the transaction to make the information visible to the slave. | 41 | # commit the transaction to make the information visible to the |
301 | 42 | # standby. | ||
302 | 42 | transaction.commit() | 43 | transaction.commit() |
303 | 43 | cloud_info = self._branch_cloud.getProductsWithInfo(num_products) | 44 | cloud_info = self._branch_cloud.getProductsWithInfo(num_products) |
304 | 44 | 45 | ||
305 | diff --git a/lib/lp/registry/scripts/teamparticipation.py b/lib/lp/registry/scripts/teamparticipation.py | |||
306 | index cfca76a..cb15dff 100644 | |||
307 | --- a/lib/lp/registry/scripts/teamparticipation.py | |||
308 | +++ b/lib/lp/registry/scripts/teamparticipation.py | |||
309 | @@ -30,7 +30,7 @@ from lp.registry.interfaces.teammembership import ACTIVE_STATES | |||
310 | 30 | from lp.registry.model.teammembership import TeamParticipation | 30 | from lp.registry.model.teammembership import TeamParticipation |
311 | 31 | from lp.services.database.interfaces import ( | 31 | from lp.services.database.interfaces import ( |
312 | 32 | IMasterStore, | 32 | IMasterStore, |
314 | 33 | ISlaveStore, | 33 | IStandbyStore, |
315 | 34 | ) | 34 | ) |
316 | 35 | from lp.services.database.sqlbase import ( | 35 | from lp.services.database.sqlbase import ( |
317 | 36 | quote, | 36 | quote, |
318 | @@ -52,7 +52,7 @@ def check_teamparticipation_circular(log): | |||
319 | 52 | AND tp.person = tp2.team | 52 | AND tp.person = tp2.team |
320 | 53 | AND tp.id != tp2.id; | 53 | AND tp.id != tp2.id; |
321 | 54 | """ | 54 | """ |
323 | 55 | circular_references = list(ISlaveStore(TeamParticipation).execute(query)) | 55 | circular_references = list(IStandbyStore(TeamParticipation).execute(query)) |
324 | 56 | if len(circular_references) > 0: | 56 | if len(circular_references) > 0: |
325 | 57 | raise LaunchpadScriptFailure( | 57 | raise LaunchpadScriptFailure( |
326 | 58 | "Circular references found: %s" % circular_references) | 58 | "Circular references found: %s" % circular_references) |
327 | @@ -93,7 +93,7 @@ def execute_long_query(store, log, interval, query): | |||
328 | 93 | def fetch_team_participation_info(log): | 93 | def fetch_team_participation_info(log): |
329 | 94 | """Fetch people, teams, memberships and participations.""" | 94 | """Fetch people, teams, memberships and participations.""" |
330 | 95 | slurp = partial( | 95 | slurp = partial( |
332 | 96 | execute_long_query, ISlaveStore(TeamParticipation), log, 10000) | 96 | execute_long_query, IStandbyStore(TeamParticipation), log, 10000) |
333 | 97 | 97 | ||
334 | 98 | people = dict( | 98 | people = dict( |
335 | 99 | slurp( | 99 | slurp( |
336 | diff --git a/lib/lp/services/database/doc/db-policy.txt b/lib/lp/services/database/doc/db-policy.txt | |||
337 | index 8a1cce2..fbb9aae 100644 | |||
338 | --- a/lib/lp/services/database/doc/db-policy.txt | |||
339 | +++ b/lib/lp/services/database/doc/db-policy.txt | |||
340 | @@ -31,8 +31,8 @@ of the primary, the better the overall performance of Launchpad will be. | |||
341 | 31 | We can distribute this load over many standby databases but are limited to | 31 | We can distribute this load over many standby databases but are limited to |
342 | 32 | a single primary. | 32 | a single primary. |
343 | 33 | 33 | ||
346 | 34 | >>> from lp.services.database.interfaces import ISlaveStore | 34 | >>> from lp.services.database.interfaces import IStandbyStore |
347 | 35 | >>> ro_janitor = ISlaveStore(Person).find( | 35 | >>> ro_janitor = IStandbyStore(Person).find( |
348 | 36 | ... Person, Person.name == 'janitor').one() | 36 | ... Person, Person.name == 'janitor').one() |
349 | 37 | >>> ro_janitor is writable_janitor | 37 | >>> ro_janitor is writable_janitor |
350 | 38 | False | 38 | False |
351 | diff --git a/lib/lp/services/database/doc/storm-store-reset.txt b/lib/lp/services/database/doc/storm-store-reset.txt | |||
352 | index 8380370..b22a9a6 100644 | |||
353 | --- a/lib/lp/services/database/doc/storm-store-reset.txt | |||
354 | +++ b/lib/lp/services/database/doc/storm-store-reset.txt | |||
355 | @@ -28,7 +28,7 @@ we rely on that to find out whether or not to reset stores. | |||
356 | 28 | ... http = setupBrowser(auth="Basic foo.bar@canonical.com:test") | 28 | ... http = setupBrowser(auth="Basic foo.bar@canonical.com:test") |
357 | 29 | ... http.open("http://launchpad.test/~salgado/+edit") | 29 | ... http.open("http://launchpad.test/~salgado/+edit") |
358 | 30 | ... http.getControl("Display Name").value = "Changed" | 30 | ... http.getControl("Display Name").value = "Changed" |
360 | 31 | ... # Need a POST or the DB policy will be using the slave. | 31 | ... # Need a POST or the DB policy will be using the standby. |
361 | 32 | ... http.getControl("Save Changes").click() | 32 | ... http.getControl("Save Changes").click() |
362 | 33 | ... alive_items = len(IStore(Person)._alive) | 33 | ... alive_items = len(IStore(Person)._alive) |
363 | 34 | 34 | ||
364 | diff --git a/lib/lp/services/database/doc/storm.txt b/lib/lp/services/database/doc/storm.txt | |||
365 | index 82823a5..2690d05 100644 | |||
366 | --- a/lib/lp/services/database/doc/storm.txt | |||
367 | +++ b/lib/lp/services/database/doc/storm.txt | |||
368 | @@ -4,7 +4,7 @@ back into the main replication set as part of login server separation. | |||
369 | 4 | -- StuartBishop 20100222 | 4 | -- StuartBishop 20100222 |
370 | 5 | 5 | ||
371 | 6 | In addition to what Storm provides, we also have some Launchpad | 6 | In addition to what Storm provides, we also have some Launchpad |
373 | 7 | specific Storm tools to cope with our master and slave store arrangement. | 7 | specific Storm tools to cope with our master and standby store arrangement. |
374 | 8 | 8 | ||
375 | 9 | >>> from lp.services.identity.interfaces.emailaddress import ( | 9 | >>> from lp.services.identity.interfaces.emailaddress import ( |
376 | 10 | ... EmailAddressStatus, | 10 | ... EmailAddressStatus, |
377 | @@ -13,7 +13,7 @@ specific Storm tools to cope with our master and slave store arrangement. | |||
378 | 13 | >>> from lp.services.database.interfaces import ( | 13 | >>> from lp.services.database.interfaces import ( |
379 | 14 | ... IMasterObject, | 14 | ... IMasterObject, |
380 | 15 | ... IMasterStore, | 15 | ... IMasterStore, |
382 | 16 | ... ISlaveStore, | 16 | ... IStandbyStore, |
383 | 17 | ... IStore, | 17 | ... IStore, |
384 | 18 | ... ) | 18 | ... ) |
385 | 19 | >>> from lp.services.identity.model.emailaddress import EmailAddress | 19 | >>> from lp.services.identity.model.emailaddress import EmailAddress |
386 | @@ -33,33 +33,33 @@ provides. | |||
387 | 33 | 33 | ||
388 | 34 | >>> IMasterStore.providedBy(main_master) | 34 | >>> IMasterStore.providedBy(main_master) |
389 | 35 | True | 35 | True |
391 | 36 | >>> ISlaveStore.providedBy(main_master) | 36 | >>> IStandbyStore.providedBy(main_master) |
392 | 37 | False | 37 | False |
393 | 38 | 38 | ||
394 | 39 | 39 | ||
396 | 40 | Changes to the slave Stores will lag behind the master Stores. If | 40 | Changes to the standby Stores will lag behind the master Stores. If |
397 | 41 | you only need to read an object but require it to be in sync with the | 41 | you only need to read an object but require it to be in sync with the |
398 | 42 | master, you should use the default Store. Launchpad will give you the | 42 | master, you should use the default Store. Launchpad will give you the |
400 | 43 | slave store if it is sure all your recent changes have been replicated. | 43 | standby store if it is sure all your recent changes have been replicated. |
401 | 44 | Otherwise, it gives you the master. See IStoreSelector for details. | 44 | Otherwise, it gives you the master. See IStoreSelector for details. |
402 | 45 | 45 | ||
403 | 46 | >>> main_default = IStore(Person) | 46 | >>> main_default = IStore(Person) |
405 | 47 | >>> main_slave = ISlaveStore(Person) | 47 | >>> main_standby = IStandbyStore(Person) |
406 | 48 | >>> main_default is main_master | 48 | >>> main_default is main_master |
407 | 49 | True | 49 | True |
409 | 50 | >>> main_default is main_slave | 50 | >>> main_default is main_standby |
410 | 51 | False | 51 | False |
411 | 52 | 52 | ||
412 | 53 | 53 | ||
413 | 54 | You can also adapt database object instances to Stores, although | 54 | You can also adapt database object instances to Stores, although |
414 | 55 | this is less generally useful. | 55 | this is less generally useful. |
415 | 56 | 56 | ||
418 | 57 | >>> janitor = ISlaveStore(Person).find(Person, name='janitor').one() | 57 | >>> janitor = IStandbyStore(Person).find(Person, name='janitor').one() |
419 | 58 | >>> ISlaveStore(janitor) is ISlaveStore(Person) | 58 | >>> IStandbyStore(janitor) is IStandbyStore(Person) |
420 | 59 | True | 59 | True |
421 | 60 | >>> IMasterStore(janitor) is IMasterStore(Person) | 60 | >>> IMasterStore(janitor) is IMasterStore(Person) |
422 | 61 | True | 61 | True |
424 | 62 | >>> IMasterStore(janitor) is ISlaveStore(Person) | 62 | >>> IMasterStore(janitor) is IStandbyStore(Person) |
425 | 63 | False | 63 | False |
426 | 64 | 64 | ||
427 | 65 | 65 | ||
428 | @@ -68,9 +68,9 @@ Good defensive programming is to use this adapter if you want to make | |||
429 | 68 | changes to an object, just in case you have been passed an instance | 68 | changes to an object, just in case you have been passed an instance |
430 | 69 | from a store other than the correct Master. | 69 | from a store other than the correct Master. |
431 | 70 | 70 | ||
433 | 71 | >>> main_slave = ISlaveStore(Person) | 71 | >>> main_standby = IStandbyStore(Person) |
434 | 72 | >>> t = transaction.begin() | 72 | >>> t = transaction.begin() |
436 | 73 | >>> person = main_slave.find(Person, name='mark').one() | 73 | >>> person = main_standby.find(Person, name='mark').one() |
437 | 74 | >>> person.display_name = 'Cannot change' | 74 | >>> person.display_name = 'Cannot change' |
438 | 75 | >>> transaction.commit() | 75 | >>> transaction.commit() |
439 | 76 | Traceback (most recent call last): | 76 | Traceback (most recent call last): |
440 | @@ -79,7 +79,7 @@ from a store other than the correct Master. | |||
441 | 79 | 79 | ||
442 | 80 | >>> transaction.abort() | 80 | >>> transaction.abort() |
443 | 81 | >>> t = transaction.begin() | 81 | >>> t = transaction.begin() |
445 | 82 | >>> person = main_slave.find(Person, name='mark').one() | 82 | >>> person = main_standby.find(Person, name='mark').one() |
446 | 83 | >>> IMasterObject(person).display_name = 'Can change' | 83 | >>> IMasterObject(person).display_name = 'Can change' |
447 | 84 | >>> transaction.commit() | 84 | >>> transaction.commit() |
448 | 85 | 85 | ||
449 | @@ -121,14 +121,14 @@ stores. | |||
450 | 121 | >>> master_email = IMasterStore(EmailAddress).find( | 121 | >>> master_email = IMasterStore(EmailAddress).find( |
451 | 122 | ... EmailAddress, Person.name == 'janitor', | 122 | ... EmailAddress, Person.name == 'janitor', |
452 | 123 | ... EmailAddress.person==Person.id).one() | 123 | ... EmailAddress.person==Person.id).one() |
454 | 124 | >>> slave_email = ISlaveStore(EmailAddress).find( | 124 | >>> standby_email = IStandbyStore(EmailAddress).find( |
455 | 125 | ... EmailAddress, Person.name == 'janitor', | 125 | ... EmailAddress, Person.name == 'janitor', |
456 | 126 | ... EmailAddress.person==Person.id).one() | 126 | ... EmailAddress.person==Person.id).one() |
458 | 127 | >>> master_email is slave_email | 127 | >>> master_email is standby_email |
459 | 128 | False | 128 | False |
461 | 129 | >>> master_email == slave_email | 129 | >>> master_email == standby_email |
462 | 130 | True | 130 | True |
464 | 131 | >>> master_email != slave_email | 131 | >>> master_email != standby_email |
465 | 132 | False | 132 | False |
466 | 133 | 133 | ||
467 | 134 | Comparison works for security wrapped objects too. | 134 | Comparison works for security wrapped objects too. |
468 | diff --git a/lib/lp/services/database/interfaces.py b/lib/lp/services/database/interfaces.py | |||
469 | index 5e89515..aae6350 100644 | |||
470 | --- a/lib/lp/services/database/interfaces.py | |||
471 | +++ b/lib/lp/services/database/interfaces.py | |||
472 | @@ -9,8 +9,8 @@ __all__ = [ | |||
473 | 9 | 'IMasterObject', | 9 | 'IMasterObject', |
474 | 10 | 'IMasterStore', | 10 | 'IMasterStore', |
475 | 11 | 'IRequestExpired', | 11 | 'IRequestExpired', |
476 | 12 | 'ISlaveStore', | ||
477 | 13 | 'ISQLBase', | 12 | 'ISQLBase', |
478 | 13 | 'IStandbyStore', | ||
479 | 14 | 'IStore', | 14 | 'IStore', |
480 | 15 | 'IStoreSelector', | 15 | 'IStoreSelector', |
481 | 16 | 'MAIN_STORE', | 16 | 'MAIN_STORE', |
482 | @@ -153,7 +153,7 @@ class IMasterStore(IStore): | |||
483 | 153 | """A writeable Storm Stores.""" | 153 | """A writeable Storm Stores.""" |
484 | 154 | 154 | ||
485 | 155 | 155 | ||
487 | 156 | class ISlaveStore(IStore): | 156 | class IStandbyStore(IStore): |
488 | 157 | """A read-only Storm Store.""" | 157 | """A read-only Storm Store.""" |
489 | 158 | 158 | ||
490 | 159 | 159 | ||
491 | diff --git a/lib/lp/services/database/policy.py b/lib/lp/services/database/policy.py | |||
492 | index a50fe3d..8d8f4e3 100644 | |||
493 | --- a/lib/lp/services/database/policy.py | |||
494 | +++ b/lib/lp/services/database/policy.py | |||
495 | @@ -44,7 +44,7 @@ from lp.services.database.interfaces import ( | |||
496 | 44 | DisallowedStore, | 44 | DisallowedStore, |
497 | 45 | IDatabasePolicy, | 45 | IDatabasePolicy, |
498 | 46 | IMasterStore, | 46 | IMasterStore, |
500 | 47 | ISlaveStore, | 47 | IStandbyStore, |
501 | 48 | IStoreSelector, | 48 | IStoreSelector, |
502 | 49 | MAIN_STORE, | 49 | MAIN_STORE, |
503 | 50 | PRIMARY_FLAVOR, | 50 | PRIMARY_FLAVOR, |
504 | @@ -158,7 +158,7 @@ class BaseDatabasePolicy: | |||
505 | 158 | if flavor == PRIMARY_FLAVOR: | 158 | if flavor == PRIMARY_FLAVOR: |
506 | 159 | alsoProvides(store, IMasterStore) | 159 | alsoProvides(store, IMasterStore) |
507 | 160 | else: | 160 | else: |
509 | 161 | alsoProvides(store, ISlaveStore) | 161 | alsoProvides(store, IStandbyStore) |
510 | 162 | 162 | ||
511 | 163 | store._lp_store_initialized = True | 163 | store._lp_store_initialized = True |
512 | 164 | 164 | ||
513 | diff --git a/lib/lp/services/database/tests/test_bulk.py b/lib/lp/services/database/tests/test_bulk.py | |||
514 | index a90d11e..78981ae 100644 | |||
515 | --- a/lib/lp/services/database/tests/test_bulk.py | |||
516 | +++ b/lib/lp/services/database/tests/test_bulk.py | |||
517 | @@ -30,7 +30,7 @@ from lp.registry.model.person import Person | |||
518 | 30 | from lp.services.database import bulk | 30 | from lp.services.database import bulk |
519 | 31 | from lp.services.database.interfaces import ( | 31 | from lp.services.database.interfaces import ( |
520 | 32 | IMasterStore, | 32 | IMasterStore, |
522 | 33 | ISlaveStore, | 33 | IStandbyStore, |
523 | 34 | IStore, | 34 | IStore, |
524 | 35 | ) | 35 | ) |
525 | 36 | from lp.services.database.sqlbase import ( | 36 | from lp.services.database.sqlbase import ( |
526 | @@ -131,13 +131,13 @@ class TestLoaders(TestCaseWithFactory): | |||
527 | 131 | db_object = self.factory.makeComponent() | 131 | db_object = self.factory.makeComponent() |
528 | 132 | db_object_type = bulk.get_type(db_object) | 132 | db_object_type = bulk.get_type(db_object) |
529 | 133 | # Commit so the database object is available in both master | 133 | # Commit so the database object is available in both master |
531 | 134 | # and slave stores. | 134 | # and standby stores. |
532 | 135 | transaction.commit() | 135 | transaction.commit() |
533 | 136 | # Use a list, since objects corresponding to the same DB row from | 136 | # Use a list, since objects corresponding to the same DB row from |
534 | 137 | # different stores compare equal. | 137 | # different stores compare equal. |
535 | 138 | db_objects = [ | 138 | db_objects = [ |
536 | 139 | IMasterStore(db_object).get(db_object_type, db_object.id), | 139 | IMasterStore(db_object).get(db_object_type, db_object.id), |
538 | 140 | ISlaveStore(db_object).get(db_object_type, db_object.id), | 140 | IStandbyStore(db_object).get(db_object_type, db_object.id), |
539 | 141 | ] | 141 | ] |
540 | 142 | db_object_ids = {id(obj) for obj in db_objects} | 142 | db_object_ids = {id(obj) for obj in db_objects} |
541 | 143 | db_queries = list(bulk.gen_reload_queries(db_objects)) | 143 | db_queries = list(bulk.gen_reload_queries(db_objects)) |
542 | @@ -234,7 +234,7 @@ class TestLoaders(TestCaseWithFactory): | |||
543 | 234 | # load() can use an alternative store. | 234 | # load() can use an alternative store. |
544 | 235 | db_object = self.factory.makeComponent() | 235 | db_object = self.factory.makeComponent() |
545 | 236 | # Commit so the database object is available in both master | 236 | # Commit so the database object is available in both master |
547 | 237 | # and slave stores. | 237 | # and standby stores. |
548 | 238 | transaction.commit() | 238 | transaction.commit() |
549 | 239 | # Master store. | 239 | # Master store. |
550 | 240 | master_store = IMasterStore(db_object) | 240 | master_store = IMasterStore(db_object) |
551 | @@ -242,12 +242,12 @@ class TestLoaders(TestCaseWithFactory): | |||
552 | 242 | Component, [db_object.id], store=master_store) | 242 | Component, [db_object.id], store=master_store) |
553 | 243 | self.assertEqual( | 243 | self.assertEqual( |
554 | 244 | Store.of(db_object_from_master), master_store) | 244 | Store.of(db_object_from_master), master_store) |
559 | 245 | # Slave store. | 245 | # Standby store. |
560 | 246 | slave_store = ISlaveStore(db_object) | 246 | standby_store = IStandbyStore(db_object) |
561 | 247 | [db_object_from_slave] = bulk.load( | 247 | [db_object_from_standby] = bulk.load( |
562 | 248 | Component, [db_object.id], store=slave_store) | 248 | Component, [db_object.id], store=standby_store) |
563 | 249 | self.assertEqual( | 249 | self.assertEqual( |
565 | 250 | Store.of(db_object_from_slave), slave_store) | 250 | Store.of(db_object_from_standby), standby_store) |
566 | 251 | 251 | ||
567 | 252 | def test_load_related(self): | 252 | def test_load_related(self): |
568 | 253 | owning_objects = [ | 253 | owning_objects = [ |
569 | diff --git a/lib/lp/services/database/transaction_policy.py b/lib/lp/services/database/transaction_policy.py | |||
570 | index bb1b403..8766894 100644 | |||
571 | --- a/lib/lp/services/database/transaction_policy.py | |||
572 | +++ b/lib/lp/services/database/transaction_policy.py | |||
573 | @@ -24,7 +24,7 @@ class DatabaseTransactionPolicy: | |||
574 | 24 | 24 | ||
575 | 25 | # We want to be sure that inspect_data does not inadvertently | 25 | # We want to be sure that inspect_data does not inadvertently |
576 | 26 | # make any changes in the database, but we can't run it on the | 26 | # make any changes in the database, but we can't run it on the |
578 | 27 | # slave store because it doesn't tolerate replication lag. | 27 | # standby store because it doesn't tolerate replication lag. |
579 | 28 | with DatabaseTransactionPolicy(read_only=True): | 28 | with DatabaseTransactionPolicy(read_only=True): |
580 | 29 | inspect_data() | 29 | inspect_data() |
581 | 30 | 30 | ||
582 | @@ -69,7 +69,7 @@ class DatabaseTransactionPolicy: | |||
583 | 69 | writability of database transactions. | 69 | writability of database transactions. |
584 | 70 | 70 | ||
585 | 71 | :param store: The store to set policy on. Defaults to the main master | 71 | :param store: The store to set policy on. Defaults to the main master |
587 | 72 | store. You don't want to use this on a slave store! | 72 | store. You don't want to use this on a standby store! |
588 | 73 | :param read_only: Is this policy read-only? | 73 | :param read_only: Is this policy read-only? |
589 | 74 | """ | 74 | """ |
590 | 75 | self.read_only = read_only | 75 | self.read_only = read_only |
591 | diff --git a/lib/lp/services/librarian/tests/test_client.py b/lib/lp/services/librarian/tests/test_client.py | |||
592 | index cb054a9..6bef538 100644 | |||
593 | --- a/lib/lp/services/librarian/tests/test_client.py | |||
594 | +++ b/lib/lp/services/librarian/tests/test_client.py | |||
595 | @@ -25,7 +25,7 @@ import transaction | |||
596 | 25 | 25 | ||
597 | 26 | from lp.services.config import config | 26 | from lp.services.config import config |
598 | 27 | from lp.services.daemons.tachandler import TacTestSetup | 27 | from lp.services.daemons.tachandler import TacTestSetup |
600 | 28 | from lp.services.database.interfaces import ISlaveStore | 28 | from lp.services.database.interfaces import IStandbyStore |
601 | 29 | from lp.services.database.policy import StandbyDatabasePolicy | 29 | from lp.services.database.policy import StandbyDatabasePolicy |
602 | 30 | from lp.services.database.sqlbase import block_implicit_flushes | 30 | from lp.services.database.sqlbase import block_implicit_flushes |
603 | 31 | from lp.services.librarian import client as client_module | 31 | from lp.services.librarian import client as client_module |
604 | @@ -299,7 +299,7 @@ class LibrarianClientTestCase(TestCase): | |||
605 | 299 | # standby store and try to add a file, verifying that the primary | 299 | # standby store and try to add a file, verifying that the primary |
606 | 300 | # is used. | 300 | # is used. |
607 | 301 | client = LibrarianClient() | 301 | client = LibrarianClient() |
609 | 302 | ISlaveStore(LibraryFileAlias).close() | 302 | IStandbyStore(LibraryFileAlias).close() |
610 | 303 | with StandbyDatabasePolicy(): | 303 | with StandbyDatabasePolicy(): |
611 | 304 | alias_id = client.addFile( | 304 | alias_id = client.addFile( |
612 | 305 | 'sample.txt', 6, io.BytesIO(b'sample'), 'text/plain') | 305 | 'sample.txt', 6, io.BytesIO(b'sample'), 'text/plain') |
613 | diff --git a/lib/lp/services/librarianserver/swift.py b/lib/lp/services/librarianserver/swift.py | |||
614 | index 637110f..ddb3125 100644 | |||
615 | --- a/lib/lp/services/librarianserver/swift.py | |||
616 | +++ b/lib/lp/services/librarianserver/swift.py | |||
617 | @@ -24,7 +24,7 @@ from six.moves.urllib.parse import quote | |||
618 | 24 | from swiftclient import client as swiftclient | 24 | from swiftclient import client as swiftclient |
619 | 25 | 25 | ||
620 | 26 | from lp.services.config import config | 26 | from lp.services.config import config |
622 | 27 | from lp.services.database.interfaces import ISlaveStore | 27 | from lp.services.database.interfaces import IStandbyStore |
623 | 28 | from lp.services.librarian.model import LibraryFileContent | 28 | from lp.services.librarian.model import LibraryFileContent |
624 | 29 | 29 | ||
625 | 30 | 30 | ||
626 | @@ -143,7 +143,7 @@ def to_swift(log, start_lfc_id=None, end_lfc_id=None, | |||
627 | 143 | 143 | ||
628 | 144 | log.debug('Found {} ({})'.format(lfc, filename)) | 144 | log.debug('Found {} ({})'.format(lfc, filename)) |
629 | 145 | 145 | ||
631 | 146 | if ISlaveStore(LibraryFileContent).get( | 146 | if IStandbyStore(LibraryFileContent).get( |
632 | 147 | LibraryFileContent, lfc) is None: | 147 | LibraryFileContent, lfc) is None: |
633 | 148 | log.info("{} exists on disk but not in the db".format( | 148 | log.info("{} exists on disk but not in the db".format( |
634 | 149 | lfc)) | 149 | lfc)) |
635 | @@ -205,7 +205,7 @@ def _put(log, swift_connection, lfc_id, container, obj_name, fs_path): | |||
636 | 205 | fs_size = os.path.getsize(fs_path) | 205 | fs_size = os.path.getsize(fs_path) |
637 | 206 | fs_file = HashStream(open(fs_path, 'rb')) | 206 | fs_file = HashStream(open(fs_path, 'rb')) |
638 | 207 | 207 | ||
640 | 208 | db_md5_hash = ISlaveStore(LibraryFileContent).get( | 208 | db_md5_hash = IStandbyStore(LibraryFileContent).get( |
641 | 209 | LibraryFileContent, lfc_id).md5 | 209 | LibraryFileContent, lfc_id).md5 |
642 | 210 | 210 | ||
643 | 211 | assert hasattr(fs_file, 'tell') and hasattr(fs_file, 'seek'), ''' | 211 | assert hasattr(fs_file, 'tell') and hasattr(fs_file, 'seek'), ''' |
644 | diff --git a/lib/lp/services/oauth/model.py b/lib/lp/services/oauth/model.py | |||
645 | index 3b48de6..2c07b19 100644 | |||
646 | --- a/lib/lp/services/oauth/model.py | |||
647 | +++ b/lib/lp/services/oauth/model.py | |||
648 | @@ -68,7 +68,7 @@ class OAuthBase: | |||
649 | 68 | """Return the correct store for this class. | 68 | """Return the correct store for this class. |
650 | 69 | 69 | ||
651 | 70 | We want all OAuth classes to be retrieved from the master flavour. If | 70 | We want all OAuth classes to be retrieved from the master flavour. If |
653 | 71 | they are retrieved from the slave, there will be problems in the | 71 | they are retrieved from the standby, there will be problems in the |
654 | 72 | authorization exchange, since it will be done across applications that | 72 | authorization exchange, since it will be done across applications that |
655 | 73 | won't share the session cookies. | 73 | won't share the session cookies. |
656 | 74 | """ | 74 | """ |
657 | diff --git a/lib/lp/services/session/adapters.py b/lib/lp/services/session/adapters.py | |||
658 | index 1cc2767..e2bc15b 100644 | |||
659 | --- a/lib/lp/services/session/adapters.py | |||
660 | +++ b/lib/lp/services/session/adapters.py | |||
661 | @@ -11,7 +11,7 @@ from zope.interface import implementer | |||
662 | 11 | 11 | ||
663 | 12 | from lp.services.database.interfaces import ( | 12 | from lp.services.database.interfaces import ( |
664 | 13 | IMasterStore, | 13 | IMasterStore, |
666 | 14 | ISlaveStore, | 14 | IStandbyStore, |
667 | 15 | IStore, | 15 | IStore, |
668 | 16 | ) | 16 | ) |
669 | 17 | from lp.services.database.sqlbase import session_store | 17 | from lp.services.database.sqlbase import session_store |
670 | @@ -26,9 +26,9 @@ def session_master_store(cls): | |||
671 | 26 | 26 | ||
672 | 27 | 27 | ||
673 | 28 | @adapter(IUseSessionStore) | 28 | @adapter(IUseSessionStore) |
677 | 29 | @implementer(ISlaveStore) | 29 | @implementer(IStandbyStore) |
678 | 30 | def session_slave_store(cls): | 30 | def session_standby_store(cls): |
679 | 31 | """Adapt a Session database object to an `ISlaveStore`.""" | 31 | """Adapt a Session database object to an `IStandbyStore`.""" |
680 | 32 | return session_store() | 32 | return session_store() |
681 | 33 | 33 | ||
682 | 34 | 34 | ||
683 | diff --git a/lib/lp/services/session/configure.zcml b/lib/lp/services/session/configure.zcml | |||
684 | index dea1cd8..8c3c399 100644 | |||
685 | --- a/lib/lp/services/session/configure.zcml | |||
686 | +++ b/lib/lp/services/session/configure.zcml | |||
687 | @@ -7,6 +7,6 @@ | |||
688 | 7 | xmlns:i18n="http://namespaces.zope.org/i18n" | 7 | xmlns:i18n="http://namespaces.zope.org/i18n" |
689 | 8 | i18n_domain="launchpad"> | 8 | i18n_domain="launchpad"> |
690 | 9 | <adapter factory=".adapters.session_master_store" /> | 9 | <adapter factory=".adapters.session_master_store" /> |
692 | 10 | <adapter factory=".adapters.session_slave_store" /> | 10 | <adapter factory=".adapters.session_standby_store" /> |
693 | 11 | <adapter factory=".adapters.session_default_store" /> | 11 | <adapter factory=".adapters.session_default_store" /> |
694 | 12 | </configure> | 12 | </configure> |
695 | diff --git a/lib/lp/services/session/tests/test_session.py b/lib/lp/services/session/tests/test_session.py | |||
696 | index 6f5c1c0..10cab73 100644 | |||
697 | --- a/lib/lp/services/session/tests/test_session.py | |||
698 | +++ b/lib/lp/services/session/tests/test_session.py | |||
699 | @@ -5,7 +5,7 @@ | |||
700 | 5 | 5 | ||
701 | 6 | from lp.services.database.interfaces import ( | 6 | from lp.services.database.interfaces import ( |
702 | 7 | IMasterStore, | 7 | IMasterStore, |
704 | 8 | ISlaveStore, | 8 | IStandbyStore, |
705 | 9 | IStore, | 9 | IStore, |
706 | 10 | ) | 10 | ) |
707 | 11 | from lp.services.session.model import ( | 11 | from lp.services.session.model import ( |
708 | @@ -20,7 +20,7 @@ class TestSessionModelAdapters(TestCase): | |||
709 | 20 | layer = DatabaseFunctionalLayer | 20 | layer = DatabaseFunctionalLayer |
710 | 21 | 21 | ||
711 | 22 | def test_adapters(self): | 22 | def test_adapters(self): |
713 | 23 | for adapter in [IMasterStore, ISlaveStore, IStore]: | 23 | for adapter in [IMasterStore, IStandbyStore, IStore]: |
714 | 24 | for cls in [SessionData, SessionPkgData]: | 24 | for cls in [SessionData, SessionPkgData]: |
715 | 25 | for obj in [cls, cls()]: | 25 | for obj in [cls, cls()]: |
716 | 26 | store = adapter(obj) | 26 | store = adapter(obj) |
717 | diff --git a/lib/lp/services/webapp/adapter.py b/lib/lp/services/webapp/adapter.py | |||
718 | index 26b4b6d..da15bfa 100644 | |||
719 | --- a/lib/lp/services/webapp/adapter.py | |||
720 | +++ b/lib/lp/services/webapp/adapter.py | |||
721 | @@ -750,7 +750,7 @@ class StoreSelector: | |||
722 | 750 | 750 | ||
723 | 751 | 751 | ||
724 | 752 | # We want to be able to adapt a Storm class to an IStore, IMasterStore or | 752 | # We want to be able to adapt a Storm class to an IStore, IMasterStore or |
726 | 753 | # ISlaveStore. Unfortunately, the component architecture provides no | 753 | # IStandbyStore. Unfortunately, the component architecture provides no |
727 | 754 | # way for us to declare that a class, and all its subclasses, provides | 754 | # way for us to declare that a class, and all its subclasses, provides |
728 | 755 | # a given interface. This means we need to use an global adapter. | 755 | # a given interface. This means we need to use an global adapter. |
729 | 756 | 756 | ||
730 | @@ -768,8 +768,8 @@ def get_master_store(storm_class): | |||
731 | 768 | return get_store(storm_class, PRIMARY_FLAVOR) | 768 | return get_store(storm_class, PRIMARY_FLAVOR) |
732 | 769 | 769 | ||
733 | 770 | 770 | ||
736 | 771 | def get_slave_store(storm_class): | 771 | def get_standby_store(storm_class): |
737 | 772 | """Return the master Store for the given database class.""" | 772 | """Return the standby Store for the given database class.""" |
738 | 773 | return get_store(storm_class, STANDBY_FLAVOR) | 773 | return get_store(storm_class, STANDBY_FLAVOR) |
739 | 774 | 774 | ||
740 | 775 | 775 | ||
741 | diff --git a/lib/lp/services/webapp/batching.py b/lib/lp/services/webapp/batching.py | |||
742 | index 894e6a6..b4c3b2b 100644 | |||
743 | --- a/lib/lp/services/webapp/batching.py | |||
744 | +++ b/lib/lp/services/webapp/batching.py | |||
745 | @@ -36,7 +36,7 @@ from zope.security.proxy import ( | |||
746 | 36 | from lp.app.browser.launchpad import iter_view_registrations | 36 | from lp.app.browser.launchpad import iter_view_registrations |
747 | 37 | from lp.services.config import config | 37 | from lp.services.config import config |
748 | 38 | from lp.services.database.decoratedresultset import DecoratedResultSet | 38 | from lp.services.database.decoratedresultset import DecoratedResultSet |
750 | 39 | from lp.services.database.interfaces import ISlaveStore | 39 | from lp.services.database.interfaces import IStandbyStore |
751 | 40 | from lp.services.database.sqlbase import ( | 40 | from lp.services.database.sqlbase import ( |
752 | 41 | convert_storm_clause_to_string, | 41 | convert_storm_clause_to_string, |
753 | 42 | sqlvalues, | 42 | sqlvalues, |
754 | @@ -621,7 +621,7 @@ class StormRangeFactory: | |||
755 | 621 | select = removeSecurityProxy(self.plain_resultset).get_select_expr( | 621 | select = removeSecurityProxy(self.plain_resultset).get_select_expr( |
756 | 622 | *columns) | 622 | *columns) |
757 | 623 | explain = 'EXPLAIN ' + convert_storm_clause_to_string(select) | 623 | explain = 'EXPLAIN ' + convert_storm_clause_to_string(select) |
759 | 624 | result = ISlaveStore(LibraryFileAlias).execute(explain) | 624 | result = IStandbyStore(LibraryFileAlias).execute(explain) |
760 | 625 | _rows_re = re.compile(r"rows=(\d+)\swidth=") | 625 | _rows_re = re.compile(r"rows=(\d+)\swidth=") |
761 | 626 | first_line = result.get_one()[0] | 626 | first_line = result.get_one()[0] |
762 | 627 | match = _rows_re.search(first_line) | 627 | match = _rows_re.search(first_line) |
763 | diff --git a/lib/lp/services/webapp/database.zcml b/lib/lp/services/webapp/database.zcml | |||
764 | index 2d9fcd1..c283ee1 100644 | |||
765 | --- a/lib/lp/services/webapp/database.zcml | |||
766 | +++ b/lib/lp/services/webapp/database.zcml | |||
767 | @@ -46,9 +46,9 @@ | |||
768 | 46 | factory="lp.services.webapp.adapter.get_master_store" | 46 | factory="lp.services.webapp.adapter.get_master_store" |
769 | 47 | /> | 47 | /> |
770 | 48 | <adapter | 48 | <adapter |
772 | 49 | provides="lp.services.database.interfaces.ISlaveStore" | 49 | provides="lp.services.database.interfaces.IStandbyStore" |
773 | 50 | for="zope.interface.Interface" | 50 | for="zope.interface.Interface" |
775 | 51 | factory="lp.services.webapp.adapter.get_slave_store" | 51 | factory="lp.services.webapp.adapter.get_standby_store" |
776 | 52 | /> | 52 | /> |
777 | 53 | <!-- Universal adapter needed here per Bug #591841. | 53 | <!-- Universal adapter needed here per Bug #591841. |
778 | 54 | We have no way of specifying that all subclasses of | 54 | We have no way of specifying that all subclasses of |
779 | diff --git a/lib/lp/services/webapp/doc/test_adapter_permissions.txt b/lib/lp/services/webapp/doc/test_adapter_permissions.txt | |||
780 | index 2ae057f..35d35e3 100644 | |||
781 | --- a/lib/lp/services/webapp/doc/test_adapter_permissions.txt | |||
782 | +++ b/lib/lp/services/webapp/doc/test_adapter_permissions.txt | |||
783 | @@ -5,7 +5,7 @@ traversed to from a PRIMARY_FLAVOR store. | |||
784 | 5 | Because our development environment is not replicated, we use database | 5 | Because our development environment is not replicated, we use database |
785 | 6 | permissions to ensure that tables we should not be writing to cannot | 6 | permissions to ensure that tables we should not be writing to cannot |
786 | 7 | be written to. The same permissions structure is also used on production, | 7 | be written to. The same permissions structure is also used on production, |
788 | 8 | so the Slony-I triggers blocking writes to some tables will never | 8 | so the Slony-I triggers blocking writes to replicated tables will never |
789 | 9 | actually be invoked. | 9 | actually be invoked. |
790 | 10 | 10 | ||
791 | 11 | >>> from lp.registry.model.person import Person | 11 | >>> from lp.registry.model.person import Person |
792 | diff --git a/lib/lp/services/webapp/publication.py b/lib/lp/services/webapp/publication.py | |||
793 | index 31079d6..80effc1 100644 | |||
794 | --- a/lib/lp/services/webapp/publication.py | |||
795 | +++ b/lib/lp/services/webapp/publication.py | |||
796 | @@ -703,7 +703,7 @@ class LaunchpadBrowserPublication( | |||
797 | 703 | return False | 703 | return False |
798 | 704 | 704 | ||
799 | 705 | # If we get a LookupError and the default database being | 705 | # If we get a LookupError and the default database being |
801 | 706 | # used is a replica, raise a Retry exception instead of | 706 | # used is a standby, raise a Retry exception instead of |
802 | 707 | # returning the 404 error page. We do this in case the | 707 | # returning the 404 error page. We do this in case the |
803 | 708 | # LookupError is caused by replication lag. Our database | 708 | # LookupError is caused by replication lag. Our database |
804 | 709 | # policy forces the use of the primary database for retries. | 709 | # policy forces the use of the primary database for retries. |
805 | diff --git a/lib/lp/services/webapp/tests/test_dbpolicy.py b/lib/lp/services/webapp/tests/test_dbpolicy.py | |||
806 | index 8855268..a2a8120 100644 | |||
807 | --- a/lib/lp/services/webapp/tests/test_dbpolicy.py | |||
808 | +++ b/lib/lp/services/webapp/tests/test_dbpolicy.py | |||
809 | @@ -36,7 +36,7 @@ from lp.services.database.interfaces import ( | |||
810 | 36 | DisallowedStore, | 36 | DisallowedStore, |
811 | 37 | IDatabasePolicy, | 37 | IDatabasePolicy, |
812 | 38 | IMasterStore, | 38 | IMasterStore, |
814 | 39 | ISlaveStore, | 39 | IStandbyStore, |
815 | 40 | IStoreSelector, | 40 | IStoreSelector, |
816 | 41 | MAIN_STORE, | 41 | MAIN_STORE, |
817 | 42 | PRIMARY_FLAVOR, | 42 | PRIMARY_FLAVOR, |
818 | @@ -110,7 +110,7 @@ class StandbyDatabasePolicyTestCase(BaseDatabasePolicyTestCase): | |||
819 | 110 | for store in ALL_STORES: | 110 | for store in ALL_STORES: |
820 | 111 | self.assertProvides( | 111 | self.assertProvides( |
821 | 112 | getUtility(IStoreSelector).get(store, DEFAULT_FLAVOR), | 112 | getUtility(IStoreSelector).get(store, DEFAULT_FLAVOR), |
823 | 113 | ISlaveStore) | 113 | IStandbyStore) |
824 | 114 | 114 | ||
825 | 115 | def test_primary_allowed(self): | 115 | def test_primary_allowed(self): |
826 | 116 | for store in ALL_STORES: | 116 | for store in ALL_STORES: |
827 | @@ -157,7 +157,7 @@ class PrimaryDatabasePolicyTestCase(BaseDatabasePolicyTestCase): | |||
828 | 157 | for store in ALL_STORES: | 157 | for store in ALL_STORES: |
829 | 158 | self.assertProvides( | 158 | self.assertProvides( |
830 | 159 | getUtility(IStoreSelector).get(store, STANDBY_FLAVOR), | 159 | getUtility(IStoreSelector).get(store, STANDBY_FLAVOR), |
832 | 160 | ISlaveStore) | 160 | IStandbyStore) |
833 | 161 | 161 | ||
834 | 162 | 162 | ||
835 | 163 | class LaunchpadDatabasePolicyTestCase(StandbyDatabasePolicyTestCase): | 163 | class LaunchpadDatabasePolicyTestCase(StandbyDatabasePolicyTestCase): |
836 | @@ -268,56 +268,56 @@ class PrimaryFallbackTestCase(TestCase): | |||
837 | 268 | '''Confirm that this TestCase's test infrastructure works as needed. | 268 | '''Confirm that this TestCase's test infrastructure works as needed. |
838 | 269 | ''' | 269 | ''' |
839 | 270 | master_store = IMasterStore(Person) | 270 | master_store = IMasterStore(Person) |
841 | 271 | slave_store = ISlaveStore(Person) | 271 | standby_store = IStandbyStore(Person) |
842 | 272 | 272 | ||
843 | 273 | # Both Stores work when pgbouncer is up. | 273 | # Both Stores work when pgbouncer is up. |
844 | 274 | master_store.get(Person, 1) | 274 | master_store.get(Person, 1) |
846 | 275 | slave_store.get(Person, 1) | 275 | standby_store.get(Person, 1) |
847 | 276 | 276 | ||
849 | 277 | # Slave Store breaks when pgbouncer is torn down. Master Store | 277 | # Standby Store breaks when pgbouncer is torn down. Master Store |
850 | 278 | # is fine. | 278 | # is fine. |
851 | 279 | self.pgbouncer_fixture.stop() | 279 | self.pgbouncer_fixture.stop() |
852 | 280 | master_store.get(Person, 2) | 280 | master_store.get(Person, 2) |
854 | 281 | self.assertRaises(DisconnectionError, slave_store.get, Person, 2) | 281 | self.assertRaises(DisconnectionError, standby_store.get, Person, 2) |
855 | 282 | 282 | ||
856 | 283 | def test_startup_with_no_standby(self): | 283 | def test_startup_with_no_standby(self): |
857 | 284 | '''An attempt is made for the first time to connect to a standby.''' | 284 | '''An attempt is made for the first time to connect to a standby.''' |
858 | 285 | self.pgbouncer_fixture.stop() | 285 | self.pgbouncer_fixture.stop() |
859 | 286 | 286 | ||
860 | 287 | master_store = IMasterStore(Person) | 287 | master_store = IMasterStore(Person) |
862 | 288 | slave_store = ISlaveStore(Person) | 288 | standby_store = IStandbyStore(Person) |
863 | 289 | 289 | ||
866 | 290 | # The master and slave Stores are the same object. | 290 | # The master and standby Stores are the same object. |
867 | 291 | self.assertIs(master_store, slave_store) | 291 | self.assertIs(master_store, standby_store) |
868 | 292 | 292 | ||
869 | 293 | def test_standby_shutdown_during_transaction(self): | 293 | def test_standby_shutdown_during_transaction(self): |
870 | 294 | '''Standby is shutdown while running, but we can recover.''' | 294 | '''Standby is shutdown while running, but we can recover.''' |
871 | 295 | master_store = IMasterStore(Person) | 295 | master_store = IMasterStore(Person) |
873 | 296 | slave_store = ISlaveStore(Person) | 296 | standby_store = IStandbyStore(Person) |
874 | 297 | 297 | ||
876 | 298 | self.assertIsNot(master_store, slave_store) | 298 | self.assertIsNot(master_store, standby_store) |
877 | 299 | 299 | ||
878 | 300 | self.pgbouncer_fixture.stop() | 300 | self.pgbouncer_fixture.stop() |
879 | 301 | 301 | ||
881 | 302 | # The transaction fails if the slave store is used. Robust | 302 | # The transaction fails if the standby store is used. Robust |
882 | 303 | # processes will handle this and retry (even if just means exit | 303 | # processes will handle this and retry (even if just means exit |
883 | 304 | # and wait for the next scheduled invocation). | 304 | # and wait for the next scheduled invocation). |
885 | 305 | self.assertRaises(DisconnectionError, slave_store.get, Person, 1) | 305 | self.assertRaises(DisconnectionError, standby_store.get, Person, 1) |
886 | 306 | 306 | ||
887 | 307 | transaction.abort() | 307 | transaction.abort() |
888 | 308 | 308 | ||
889 | 309 | # But in the next transaction, we get the master Store if we ask | 309 | # But in the next transaction, we get the master Store if we ask |
891 | 310 | # for the slave Store so we can continue. | 310 | # for the standby Store so we can continue. |
892 | 311 | master_store = IMasterStore(Person) | 311 | master_store = IMasterStore(Person) |
894 | 312 | slave_store = ISlaveStore(Person) | 312 | standby_store = IStandbyStore(Person) |
895 | 313 | 313 | ||
897 | 314 | self.assertIs(master_store, slave_store) | 314 | self.assertIs(master_store, standby_store) |
898 | 315 | 315 | ||
899 | 316 | def test_standby_shutdown_between_transactions(self): | 316 | def test_standby_shutdown_between_transactions(self): |
900 | 317 | '''Standby is shutdown in between transactions.''' | 317 | '''Standby is shutdown in between transactions.''' |
901 | 318 | master_store = IMasterStore(Person) | 318 | master_store = IMasterStore(Person) |
904 | 319 | slave_store = ISlaveStore(Person) | 319 | standby_store = IStandbyStore(Person) |
905 | 320 | self.assertIsNot(master_store, slave_store) | 320 | self.assertIsNot(master_store, standby_store) |
906 | 321 | 321 | ||
907 | 322 | transaction.abort() | 322 | transaction.abort() |
908 | 323 | self.pgbouncer_fixture.stop() | 323 | self.pgbouncer_fixture.stop() |
909 | @@ -325,31 +325,31 @@ class PrimaryFallbackTestCase(TestCase): | |||
910 | 325 | # The process doesn't notice the standby going down, and things | 325 | # The process doesn't notice the standby going down, and things |
911 | 326 | # will fail the next time the standby is used. | 326 | # will fail the next time the standby is used. |
912 | 327 | master_store = IMasterStore(Person) | 327 | master_store = IMasterStore(Person) |
916 | 328 | slave_store = ISlaveStore(Person) | 328 | standby_store = IStandbyStore(Person) |
917 | 329 | self.assertIsNot(master_store, slave_store) | 329 | self.assertIsNot(master_store, standby_store) |
918 | 330 | self.assertRaises(DisconnectionError, slave_store.get, Person, 1) | 330 | self.assertRaises(DisconnectionError, standby_store.get, Person, 1) |
919 | 331 | 331 | ||
920 | 332 | # But now it has been discovered the socket is no longer | 332 | # But now it has been discovered the socket is no longer |
921 | 333 | # connected to anything, next transaction we get a master | 333 | # connected to anything, next transaction we get a master |
923 | 334 | # Store when we ask for a slave. | 334 | # Store when we ask for a standby. |
924 | 335 | master_store = IMasterStore(Person) | 335 | master_store = IMasterStore(Person) |
927 | 336 | slave_store = ISlaveStore(Person) | 336 | standby_store = IStandbyStore(Person) |
928 | 337 | self.assertIs(master_store, slave_store) | 337 | self.assertIs(master_store, standby_store) |
929 | 338 | 338 | ||
930 | 339 | def test_standby_reconnect_after_outage(self): | 339 | def test_standby_reconnect_after_outage(self): |
931 | 340 | '''The standby is again used once it becomes available.''' | 340 | '''The standby is again used once it becomes available.''' |
932 | 341 | self.pgbouncer_fixture.stop() | 341 | self.pgbouncer_fixture.stop() |
933 | 342 | 342 | ||
934 | 343 | master_store = IMasterStore(Person) | 343 | master_store = IMasterStore(Person) |
937 | 344 | slave_store = ISlaveStore(Person) | 344 | standby_store = IStandbyStore(Person) |
938 | 345 | self.assertIs(master_store, slave_store) | 345 | self.assertIs(master_store, standby_store) |
939 | 346 | 346 | ||
940 | 347 | self.pgbouncer_fixture.start() | 347 | self.pgbouncer_fixture.start() |
941 | 348 | transaction.abort() | 348 | transaction.abort() |
942 | 349 | 349 | ||
943 | 350 | master_store = IMasterStore(Person) | 350 | master_store = IMasterStore(Person) |
946 | 351 | slave_store = ISlaveStore(Person) | 351 | standby_store = IStandbyStore(Person) |
947 | 352 | self.assertIsNot(master_store, slave_store) | 352 | self.assertIsNot(master_store, standby_store) |
948 | 353 | 353 | ||
949 | 354 | 354 | ||
950 | 355 | class TestFastDowntimeRollout(TestCase): | 355 | class TestFastDowntimeRollout(TestCase): |
951 | @@ -401,7 +401,7 @@ class TestFastDowntimeRollout(TestCase): | |||
952 | 401 | '''You can always access a working standby store during fast downtime. | 401 | '''You can always access a working standby store during fast downtime. |
953 | 402 | ''' | 402 | ''' |
954 | 403 | # Everything is running happily. | 403 | # Everything is running happily. |
956 | 404 | store = ISlaveStore(Person) | 404 | store = IStandbyStore(Person) |
957 | 405 | original_store = store | 405 | original_store = store |
958 | 406 | self.assertTrue(self.store_is_working(store)) | 406 | self.assertTrue(self.store_is_working(store)) |
959 | 407 | self.assertTrue(self.store_is_standby(store)) | 407 | self.assertTrue(self.store_is_standby(store)) |
960 | @@ -437,9 +437,9 @@ class TestFastDowntimeRollout(TestCase): | |||
961 | 437 | # But if we handle that and retry, we can continue. | 437 | # But if we handle that and retry, we can continue. |
962 | 438 | # Now the failed connection has been detected, the next Store | 438 | # Now the failed connection has been detected, the next Store |
963 | 439 | # we are handed is a primary Store instead of a standby. | 439 | # we are handed is a primary Store instead of a standby. |
965 | 440 | store = ISlaveStore(Person) | 440 | store = IStandbyStore(Person) |
966 | 441 | self.assertTrue(self.store_is_primary(store)) | 441 | self.assertTrue(self.store_is_primary(store)) |
968 | 442 | self.assertIsNot(ISlaveStore(Person), original_store) | 442 | self.assertIsNot(IStandbyStore(Person), original_store) |
969 | 443 | 443 | ||
970 | 444 | # But alas, it might not work the first transaction. If it has | 444 | # But alas, it might not work the first transaction. If it has |
971 | 445 | # been earlier, its connection was killed by pgbouncer earlier | 445 | # been earlier, its connection was killed by pgbouncer earlier |
972 | @@ -449,7 +449,7 @@ class TestFastDowntimeRollout(TestCase): | |||
973 | 449 | 449 | ||
974 | 450 | # Next retry attempt, everything is fine using the primary | 450 | # Next retry attempt, everything is fine using the primary |
975 | 451 | # connection, even though our code only asked for a standby. | 451 | # connection, even though our code only asked for a standby. |
977 | 452 | store = ISlaveStore(Person) | 452 | store = IStandbyStore(Person) |
978 | 453 | self.assertTrue(self.store_is_primary(store)) | 453 | self.assertTrue(self.store_is_primary(store)) |
979 | 454 | self.assertTrue(self.store_is_working(store)) | 454 | self.assertTrue(self.store_is_working(store)) |
980 | 455 | 455 | ||
981 | @@ -464,7 +464,7 @@ class TestFastDowntimeRollout(TestCase): | |||
982 | 464 | self.pgbouncer_cur.execute('ENABLE %s' % self.standby_dbname) | 464 | self.pgbouncer_cur.execute('ENABLE %s' % self.standby_dbname) |
983 | 465 | 465 | ||
984 | 466 | # And next transaction, we are back to normal. | 466 | # And next transaction, we are back to normal. |
986 | 467 | store = ISlaveStore(Person) | 467 | store = IStandbyStore(Person) |
987 | 468 | self.assertTrue(self.store_is_working(store)) | 468 | self.assertTrue(self.store_is_working(store)) |
988 | 469 | self.assertTrue(self.store_is_standby(store)) | 469 | self.assertTrue(self.store_is_standby(store)) |
989 | 470 | self.assertIs(original_store, store) | 470 | self.assertIs(original_store, store) |
990 | @@ -477,9 +477,9 @@ class TestFastDowntimeRollout(TestCase): | |||
991 | 477 | self.assertTrue(self.store_is_primary(master_store)) | 477 | self.assertTrue(self.store_is_primary(master_store)) |
992 | 478 | self.assertTrue(self.store_is_working(master_store)) | 478 | self.assertTrue(self.store_is_working(master_store)) |
993 | 479 | 479 | ||
997 | 480 | slave_store = ISlaveStore(Person) | 480 | standby_store = IStandbyStore(Person) |
998 | 481 | self.assertTrue(self.store_is_standby(slave_store)) | 481 | self.assertTrue(self.store_is_standby(standby_store)) |
999 | 482 | self.assertTrue(self.store_is_working(slave_store)) | 482 | self.assertTrue(self.store_is_working(standby_store)) |
1000 | 483 | 483 | ||
1001 | 484 | # But fast downtime is about to happen. | 484 | # But fast downtime is about to happen. |
1002 | 485 | 485 | ||
1003 | @@ -492,7 +492,7 @@ class TestFastDowntimeRollout(TestCase): | |||
1004 | 492 | self.pgbouncer_cur.execute('KILL %s' % self.primary_dbname) | 492 | self.pgbouncer_cur.execute('KILL %s' % self.primary_dbname) |
1005 | 493 | 493 | ||
1006 | 494 | # Of course, standby connections are unaffected. | 494 | # Of course, standby connections are unaffected. |
1008 | 495 | self.assertTrue(self.store_is_working(slave_store)) | 495 | self.assertTrue(self.store_is_working(standby_store)) |
1009 | 496 | 496 | ||
1010 | 497 | # But attempts to use a primary store will fail. | 497 | # But attempts to use a primary store will fail. |
1011 | 498 | self.assertFalse(self.store_is_working(master_store)) | 498 | self.assertFalse(self.store_is_working(master_store)) |
1012 | @@ -515,18 +515,18 @@ class TestFastDowntimeRollout(TestCase): | |||
1013 | 515 | 515 | ||
1014 | 516 | # The next attempt at accessing the standby store will fail | 516 | # The next attempt at accessing the standby store will fail |
1015 | 517 | # with a DisconnectionError. | 517 | # with a DisconnectionError. |
1018 | 518 | slave_store = ISlaveStore(Person) | 518 | standby_store = IStandbyStore(Person) |
1019 | 519 | self.assertTrue(self.store_is_standby(slave_store)) | 519 | self.assertTrue(self.store_is_standby(standby_store)) |
1020 | 520 | self.assertRaises( | 520 | self.assertRaises( |
1022 | 521 | DisconnectionError, slave_store.execute, 'SELECT TRUE') | 521 | DisconnectionError, standby_store.execute, 'SELECT TRUE') |
1023 | 522 | transaction.abort() | 522 | transaction.abort() |
1024 | 523 | 523 | ||
1025 | 524 | # But if we handle that and retry, we can continue. | 524 | # But if we handle that and retry, we can continue. |
1026 | 525 | # Now the failed connection has been detected, the next Store | 525 | # Now the failed connection has been detected, the next Store |
1027 | 526 | # we are handed is a primary Store instead of a standby. | 526 | # we are handed is a primary Store instead of a standby. |
1031 | 527 | slave_store = ISlaveStore(Person) | 527 | standby_store = IStandbyStore(Person) |
1032 | 528 | self.assertTrue(self.store_is_primary(slave_store)) | 528 | self.assertTrue(self.store_is_primary(standby_store)) |
1033 | 529 | self.assertTrue(self.store_is_working(slave_store)) | 529 | self.assertTrue(self.store_is_working(standby_store)) |
1034 | 530 | 530 | ||
1035 | 531 | # Once replication has caught up, the standby is reenabled. | 531 | # Once replication has caught up, the standby is reenabled. |
1036 | 532 | self.pgbouncer_cur.execute('RESUME %s' % self.standby_dbname) | 532 | self.pgbouncer_cur.execute('RESUME %s' % self.standby_dbname) |
1037 | @@ -538,6 +538,6 @@ class TestFastDowntimeRollout(TestCase): | |||
1038 | 538 | self.assertTrue(self.store_is_primary(master_store)) | 538 | self.assertTrue(self.store_is_primary(master_store)) |
1039 | 539 | self.assertTrue(self.store_is_working(master_store)) | 539 | self.assertTrue(self.store_is_working(master_store)) |
1040 | 540 | 540 | ||
1044 | 541 | slave_store = ISlaveStore(Person) | 541 | standby_store = IStandbyStore(Person) |
1045 | 542 | self.assertTrue(self.store_is_standby(slave_store)) | 542 | self.assertTrue(self.store_is_standby(standby_store)) |
1046 | 543 | self.assertTrue(self.store_is_working(slave_store)) | 543 | self.assertTrue(self.store_is_working(standby_store)) |
1047 | diff --git a/lib/lp/services/worlddata/model/language.py b/lib/lp/services/worlddata/model/language.py | |||
1048 | index aaff902..d4af9d6 100644 | |||
1049 | --- a/lib/lp/services/worlddata/model/language.py | |||
1050 | +++ b/lib/lp/services/worlddata/model/language.py | |||
1051 | @@ -26,7 +26,7 @@ from lp.registry.model.karma import ( | |||
1052 | 26 | from lp.services.database.decoratedresultset import DecoratedResultSet | 26 | from lp.services.database.decoratedresultset import DecoratedResultSet |
1053 | 27 | from lp.services.database.enumcol import DBEnum | 27 | from lp.services.database.enumcol import DBEnum |
1054 | 28 | from lp.services.database.interfaces import ( | 28 | from lp.services.database.interfaces import ( |
1056 | 29 | ISlaveStore, | 29 | IStandbyStore, |
1057 | 30 | IStore, | 30 | IStore, |
1058 | 31 | ) | 31 | ) |
1059 | 32 | from lp.services.database.sqlbase import SQLBase | 32 | from lp.services.database.sqlbase import SQLBase |
1060 | @@ -292,7 +292,7 @@ class LanguageSet: | |||
1061 | 292 | """See `ILanguageSet`.""" | 292 | """See `ILanguageSet`.""" |
1062 | 293 | if text: | 293 | if text: |
1063 | 294 | text = six.ensure_text(text).lower() | 294 | text = six.ensure_text(text).lower() |
1065 | 295 | results = ISlaveStore(Language).find( | 295 | results = IStandbyStore(Language).find( |
1066 | 296 | Language, Or( | 296 | Language, Or( |
1067 | 297 | Language.code.lower().contains_string(text), | 297 | Language.code.lower().contains_string(text), |
1068 | 298 | Language.englishname.lower().contains_string( | 298 | Language.englishname.lower().contains_string( |
1069 | diff --git a/lib/lp/soyuz/model/archive.py b/lib/lp/soyuz/model/archive.py | |||
1070 | index b3c7798..59312ea 100644 | |||
1071 | --- a/lib/lp/soyuz/model/archive.py | |||
1072 | +++ b/lib/lp/soyuz/model/archive.py | |||
1073 | @@ -105,7 +105,7 @@ from lp.services.database.datetimecol import UtcDateTimeCol | |||
1074 | 105 | from lp.services.database.decoratedresultset import DecoratedResultSet | 105 | from lp.services.database.decoratedresultset import DecoratedResultSet |
1075 | 106 | from lp.services.database.enumcol import DBEnum | 106 | from lp.services.database.enumcol import DBEnum |
1076 | 107 | from lp.services.database.interfaces import ( | 107 | from lp.services.database.interfaces import ( |
1078 | 108 | ISlaveStore, | 108 | IStandbyStore, |
1079 | 109 | IStore, | 109 | IStore, |
1080 | 110 | ) | 110 | ) |
1081 | 111 | from lp.services.database.sqlbase import ( | 111 | from lp.services.database.sqlbase import ( |
1082 | @@ -1097,7 +1097,7 @@ class Archive(SQLBase): | |||
1083 | 1097 | Component.name.is_in(components)) | 1097 | Component.name.is_in(components)) |
1084 | 1098 | for (archive, not_used, pocket, components) in deps]) | 1098 | for (archive, not_used, pocket, components) in deps]) |
1085 | 1099 | 1099 | ||
1087 | 1100 | return ISlaveStore(BinaryPackagePublishingHistory).find( | 1100 | return IStandbyStore(BinaryPackagePublishingHistory).find( |
1088 | 1101 | BinaryPackagePublishingHistory, | 1101 | BinaryPackagePublishingHistory, |
1089 | 1102 | BinaryPackageName.name == dep_name, | 1102 | BinaryPackageName.name == dep_name, |
1090 | 1103 | BinaryPackagePublishingHistory.binarypackagename == | 1103 | BinaryPackagePublishingHistory.binarypackagename == |
1091 | diff --git a/lib/lp/soyuz/tests/test_archive.py b/lib/lp/soyuz/tests/test_archive.py | |||
1092 | index 9e7be9a..cbc40ac 100644 | |||
1093 | --- a/lib/lp/soyuz/tests/test_archive.py | |||
1094 | +++ b/lib/lp/soyuz/tests/test_archive.py | |||
1095 | @@ -1901,7 +1901,7 @@ class TestFindDepCandidates(TestCaseWithFactory): | |||
1096 | 1901 | archive, and compares it to the given expected value. | 1901 | archive, and compares it to the given expected value. |
1097 | 1902 | The archive defaults to self.archive. | 1902 | The archive defaults to self.archive. |
1098 | 1903 | 1903 | ||
1100 | 1904 | Also commits, since findDepCandidates uses the slave store. | 1904 | Also commits, since findDepCandidates uses the standby store. |
1101 | 1905 | """ | 1905 | """ |
1102 | 1906 | transaction.commit() | 1906 | transaction.commit() |
1103 | 1907 | 1907 | ||
1104 | diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py | |||
1105 | index 71265f7..1588aad 100644 | |||
1106 | --- a/lib/lp/testing/factory.py | |||
1107 | +++ b/lib/lp/testing/factory.py | |||
1108 | @@ -397,7 +397,7 @@ def default_master_store(func): | |||
1109 | 397 | 397 | ||
1110 | 398 | In some cases, such as in the middle of a page test story, | 398 | In some cases, such as in the middle of a page test story, |
1111 | 399 | we might be calling factory methods with the default Store set | 399 | we might be calling factory methods with the default Store set |
1113 | 400 | to the slave which breaks stuff. For instance, if we set an account's | 400 | to the standby which breaks stuff. For instance, if we set an account's |
1114 | 401 | password that needs to happen on the master store and this is forced. | 401 | password that needs to happen on the master store and this is forced. |
1115 | 402 | However, if we then read it back the default Store has to be used. | 402 | However, if we then read it back the default Store has to be used. |
1116 | 403 | """ | 403 | """ |
1117 | diff --git a/lib/lp/translations/doc/poexport-request.txt b/lib/lp/translations/doc/poexport-request.txt | |||
1118 | index ba2b666..18d685d 100644 | |||
1119 | --- a/lib/lp/translations/doc/poexport-request.txt | |||
1120 | +++ b/lib/lp/translations/doc/poexport-request.txt | |||
1121 | @@ -33,7 +33,7 @@ Our user requests the Catalan and Czech translations of a template. | |||
1122 | 33 | 33 | ||
1123 | 34 | Now we request that the queue be processed. | 34 | Now we request that the queue be processed. |
1124 | 35 | 35 | ||
1126 | 36 | (Commits are needed to make the test requests seep through to the slave | 36 | (Commits are needed to make the test requests seep through to the standby |
1127 | 37 | database). | 37 | database). |
1128 | 38 | 38 | ||
1129 | 39 | >>> import transaction | 39 | >>> import transaction |
1130 | diff --git a/lib/lp/translations/doc/poexportqueue-replication-lag.txt b/lib/lp/translations/doc/poexportqueue-replication-lag.txt | |||
1131 | index 409fb71..e737cfc 100644 | |||
1132 | --- a/lib/lp/translations/doc/poexportqueue-replication-lag.txt | |||
1133 | +++ b/lib/lp/translations/doc/poexportqueue-replication-lag.txt | |||
1134 | @@ -2,7 +2,7 @@ Replication Lag and the Export Queue | |||
1135 | 2 | ==================================== | 2 | ==================================== |
1136 | 3 | 3 | ||
1137 | 4 | Due to replication lag it's possible for the export queue to see a | 4 | Due to replication lag it's possible for the export queue to see a |
1139 | 5 | request on the slave store that it actually just removed from the master | 5 | request on the standby store that it actually just removed from the master |
1140 | 6 | store. | 6 | store. |
1141 | 7 | 7 | ||
1142 | 8 | We start our story with an empty export queue. | 8 | We start our story with an empty export queue. |
1143 | @@ -71,7 +71,7 @@ were to ask again. | |||
1144 | 71 | ja | 71 | ja |
1145 | 72 | 72 | ||
1146 | 73 | The first request is removed from the master store after processing, but | 73 | The first request is removed from the master store after processing, but |
1148 | 74 | not yet from the slave store. (Since this test is all one session, we | 74 | not yet from the standby store. (Since this test is all one session, we |
1149 | 75 | can reproduce this by not committing the removal). The second request | 75 | can reproduce this by not committing the removal). The second request |
1150 | 76 | is still technically on the queue, but no longer "live." | 76 | is still technically on the queue, but no longer "live." |
1151 | 77 | 77 | ||
1152 | diff --git a/lib/lp/translations/doc/potmsgset.txt b/lib/lp/translations/doc/potmsgset.txt | |||
1153 | index a7a8d79..da86a39 100644 | |||
1154 | --- a/lib/lp/translations/doc/potmsgset.txt | |||
1155 | +++ b/lib/lp/translations/doc/potmsgset.txt | |||
1156 | @@ -4,7 +4,7 @@ POTMsgSet tests | |||
1157 | 4 | POTMsgSet represents messages to translate that a POTemplate file has. | 4 | POTMsgSet represents messages to translate that a POTemplate file has. |
1158 | 5 | 5 | ||
1159 | 6 | In this test we'll be committing a lot to let changes replicate to the | 6 | In this test we'll be committing a lot to let changes replicate to the |
1161 | 7 | slave database. | 7 | standby database. |
1162 | 8 | 8 | ||
1163 | 9 | >>> import transaction | 9 | >>> import transaction |
1164 | 10 | 10 | ||
1165 | diff --git a/lib/lp/translations/interfaces/poexportrequest.py b/lib/lp/translations/interfaces/poexportrequest.py | |||
1166 | index de4ad9b..2d0968b 100644 | |||
1167 | --- a/lib/lp/translations/interfaces/poexportrequest.py | |||
1168 | +++ b/lib/lp/translations/interfaces/poexportrequest.py | |||
1169 | @@ -47,7 +47,7 @@ class IPOExportRequestSet(Interface): | |||
1170 | 47 | * The requested `TranslationFileFormat`. | 47 | * The requested `TranslationFileFormat`. |
1171 | 48 | * The list of request record ids making up this request. | 48 | * The list of request record ids making up this request. |
1172 | 49 | 49 | ||
1174 | 50 | The objects are all read-only objects from the slave store. The | 50 | The objects are all read-only objects from the standby store. The |
1175 | 51 | request ids list should be passed to `removeRequest` when | 51 | request ids list should be passed to `removeRequest` when |
1176 | 52 | processing of the request completes. | 52 | processing of the request completes. |
1177 | 53 | """ | 53 | """ |
1178 | diff --git a/lib/lp/translations/interfaces/potmsgset.py b/lib/lp/translations/interfaces/potmsgset.py | |||
1179 | index 4af6b3d..3390f5f 100644 | |||
1180 | --- a/lib/lp/translations/interfaces/potmsgset.py | |||
1181 | +++ b/lib/lp/translations/interfaces/potmsgset.py | |||
1182 | @@ -172,7 +172,7 @@ class IPOTMsgSet(Interface): | |||
1183 | 172 | `POTMsgSet` that are actually used (i.e. current or imported) in | 172 | `POTMsgSet` that are actually used (i.e. current or imported) in |
1184 | 173 | other templates. | 173 | other templates. |
1185 | 174 | 174 | ||
1187 | 175 | The suggestions are read-only; they come from the slave store. | 175 | The suggestions are read-only; they come from the standby store. |
1188 | 176 | 176 | ||
1189 | 177 | :param language: language we want translations for. | 177 | :param language: language we want translations for. |
1190 | 178 | """ | 178 | """ |
1191 | @@ -184,7 +184,7 @@ class IPOTMsgSet(Interface): | |||
1192 | 184 | `POTMsgSet` that were entered in another context, but for the | 184 | `POTMsgSet` that were entered in another context, but for the |
1193 | 185 | same English text, and are not in actual use. | 185 | same English text, and are not in actual use. |
1194 | 186 | 186 | ||
1196 | 187 | The suggestions are read-only; they come from the slave store. | 187 | The suggestions are read-only; they come from the standby store. |
1197 | 188 | 188 | ||
1198 | 189 | :param language: language we want translations for. | 189 | :param language: language we want translations for. |
1199 | 190 | """ | 190 | """ |
1200 | diff --git a/lib/lp/translations/model/poexportrequest.py b/lib/lp/translations/model/poexportrequest.py | |||
1201 | index dc9b7d9..c532086 100644 | |||
1202 | --- a/lib/lp/translations/model/poexportrequest.py | |||
1203 | +++ b/lib/lp/translations/model/poexportrequest.py | |||
1204 | @@ -20,7 +20,7 @@ from lp.services.database.constants import DEFAULT | |||
1205 | 20 | from lp.services.database.enumcol import DBEnum | 20 | from lp.services.database.enumcol import DBEnum |
1206 | 21 | from lp.services.database.interfaces import ( | 21 | from lp.services.database.interfaces import ( |
1207 | 22 | IMasterStore, | 22 | IMasterStore, |
1209 | 23 | ISlaveStore, | 23 | IStandbyStore, |
1210 | 24 | IStore, | 24 | IStore, |
1211 | 25 | ) | 25 | ) |
1212 | 26 | from lp.services.database.sqlbase import quote | 26 | from lp.services.database.sqlbase import quote |
1213 | @@ -121,7 +121,7 @@ class POExportRequestSet: | |||
1214 | 121 | """Return the oldest live request on the master store. | 121 | """Return the oldest live request on the master store. |
1215 | 122 | 122 | ||
1216 | 123 | Due to replication lag, the master store is always a little | 123 | Due to replication lag, the master store is always a little |
1218 | 124 | ahead of the slave store that exports come from. | 124 | ahead of the standby store that exports come from. |
1219 | 125 | """ | 125 | """ |
1220 | 126 | master_store = IMasterStore(POExportRequest) | 126 | master_store = IMasterStore(POExportRequest) |
1221 | 127 | sorted_by_id = master_store.find(POExportRequest).order_by( | 127 | sorted_by_id = master_store.find(POExportRequest).order_by( |
1222 | @@ -130,7 +130,7 @@ class POExportRequestSet: | |||
1223 | 130 | 130 | ||
1224 | 131 | def _getHeadRequest(self): | 131 | def _getHeadRequest(self): |
1225 | 132 | """Return oldest request on the queue.""" | 132 | """Return oldest request on the queue.""" |
1227 | 133 | # Due to replication lag, it's possible that the slave store | 133 | # Due to replication lag, it's possible that the standby store |
1228 | 134 | # still has copies of requests that have already been completed | 134 | # still has copies of requests that have already been completed |
1229 | 135 | # and deleted from the master store. So first get the oldest | 135 | # and deleted from the master store. So first get the oldest |
1230 | 136 | # request that is "live," i.e. still present on the master | 136 | # request that is "live," i.e. still present on the master |
1231 | @@ -139,21 +139,21 @@ class POExportRequestSet: | |||
1232 | 139 | if oldest_live is None: | 139 | if oldest_live is None: |
1233 | 140 | return None | 140 | return None |
1234 | 141 | else: | 141 | else: |
1236 | 142 | return ISlaveStore(POExportRequest).find( | 142 | return IStandbyStore(POExportRequest).find( |
1237 | 143 | POExportRequest, | 143 | POExportRequest, |
1238 | 144 | POExportRequest.id == oldest_live.id).one() | 144 | POExportRequest.id == oldest_live.id).one() |
1239 | 145 | 145 | ||
1240 | 146 | def getRequest(self): | 146 | def getRequest(self): |
1241 | 147 | """See `IPOExportRequestSet`.""" | 147 | """See `IPOExportRequestSet`.""" |
1243 | 148 | # Exports happen off the slave store. To ensure that export | 148 | # Exports happen off the standby store. To ensure that export |
1244 | 149 | # does not happen until requests have been replicated to the | 149 | # does not happen until requests have been replicated to the |
1246 | 150 | # slave, they are read primarily from the slave even though they | 150 | # standby, they are read primarily from the standby even though they |
1247 | 151 | # are deleted on the master afterwards. | 151 | # are deleted on the master afterwards. |
1248 | 152 | head = self._getHeadRequest() | 152 | head = self._getHeadRequest() |
1249 | 153 | if head is None: | 153 | if head is None: |
1250 | 154 | return None, None, None, None | 154 | return None, None, None, None |
1251 | 155 | 155 | ||
1253 | 156 | requests = ISlaveStore(POExportRequest).find( | 156 | requests = IStandbyStore(POExportRequest).find( |
1254 | 157 | POExportRequest, | 157 | POExportRequest, |
1255 | 158 | POExportRequest.person == head.person, | 158 | POExportRequest.person == head.person, |
1256 | 159 | POExportRequest.format == head.format, | 159 | POExportRequest.format == head.format, |
1257 | diff --git a/lib/lp/translations/model/potmsgset.py b/lib/lp/translations/model/potmsgset.py | |||
1258 | index 9435564..49c4051 100644 | |||
1259 | --- a/lib/lp/translations/model/potmsgset.py | |||
1260 | +++ b/lib/lp/translations/model/potmsgset.py | |||
1261 | @@ -374,7 +374,7 @@ class POTMsgSet(SQLBase): | |||
1262 | 374 | A message is used if it's either imported or current, and unused | 374 | A message is used if it's either imported or current, and unused |
1263 | 375 | otherwise. | 375 | otherwise. |
1264 | 376 | 376 | ||
1266 | 377 | Suggestions are read-only, so these objects come from the slave | 377 | Suggestions are read-only, so these objects come from the standby |
1267 | 378 | store. | 378 | store. |
1268 | 379 | 379 | ||
1269 | 380 | :param suggested_languages: Languages that suggestions should be found | 380 | :param suggested_languages: Languages that suggestions should be found |
1270 | diff --git a/lib/lp/translations/model/translationgroup.py b/lib/lp/translations/model/translationgroup.py | |||
1271 | index ab39ddf..c274697 100644 | |||
1272 | --- a/lib/lp/translations/model/translationgroup.py | |||
1273 | +++ b/lib/lp/translations/model/translationgroup.py | |||
1274 | @@ -25,7 +25,7 @@ from lp.services.database.constants import DEFAULT | |||
1275 | 25 | from lp.services.database.datetimecol import UtcDateTimeCol | 25 | from lp.services.database.datetimecol import UtcDateTimeCol |
1276 | 26 | from lp.services.database.decoratedresultset import DecoratedResultSet | 26 | from lp.services.database.decoratedresultset import DecoratedResultSet |
1277 | 27 | from lp.services.database.interfaces import ( | 27 | from lp.services.database.interfaces import ( |
1279 | 28 | ISlaveStore, | 28 | IStandbyStore, |
1280 | 29 | IStore, | 29 | IStore, |
1281 | 30 | ) | 30 | ) |
1282 | 31 | from lp.services.database.sqlbase import SQLBase | 31 | from lp.services.database.sqlbase import SQLBase |
1283 | @@ -219,7 +219,7 @@ class TranslationGroup(SQLBase): | |||
1284 | 219 | LibraryFileAlias, | 219 | LibraryFileAlias, |
1285 | 220 | LibraryFileContent, | 220 | LibraryFileContent, |
1286 | 221 | ) | 221 | ) |
1288 | 222 | project_data = ISlaveStore(ProjectGroup).using(*using).find( | 222 | project_data = IStandbyStore(ProjectGroup).using(*using).find( |
1289 | 223 | tables, | 223 | tables, |
1290 | 224 | ProjectGroup.translationgroupID == self.id, | 224 | ProjectGroup.translationgroupID == self.id, |
1291 | 225 | ProjectGroup.active == True).order_by(ProjectGroup.display_name) | 225 | ProjectGroup.active == True).order_by(ProjectGroup.display_name) |
1292 | @@ -244,7 +244,7 @@ class TranslationGroup(SQLBase): | |||
1293 | 244 | LibraryFileAlias, | 244 | LibraryFileAlias, |
1294 | 245 | LibraryFileContent, | 245 | LibraryFileContent, |
1295 | 246 | ) | 246 | ) |
1297 | 247 | distro_data = ISlaveStore(Distribution).using(*using).find( | 247 | distro_data = IStandbyStore(Distribution).using(*using).find( |
1298 | 248 | tables, Distribution.translationgroupID == self.id).order_by( | 248 | tables, Distribution.translationgroupID == self.id).order_by( |
1299 | 249 | Distribution.display_name) | 249 | Distribution.display_name) |
1300 | 250 | 250 | ||
1301 | diff --git a/lib/lp/translations/model/translationimportqueue.py b/lib/lp/translations/model/translationimportqueue.py | |||
1302 | index 39df58b..03f85e7 100644 | |||
1303 | --- a/lib/lp/translations/model/translationimportqueue.py | |||
1304 | +++ b/lib/lp/translations/model/translationimportqueue.py | |||
1305 | @@ -60,7 +60,7 @@ from lp.services.database.constants import ( | |||
1306 | 60 | from lp.services.database.enumcol import DBEnum | 60 | from lp.services.database.enumcol import DBEnum |
1307 | 61 | from lp.services.database.interfaces import ( | 61 | from lp.services.database.interfaces import ( |
1308 | 62 | IMasterStore, | 62 | IMasterStore, |
1310 | 63 | ISlaveStore, | 63 | IStandbyStore, |
1311 | 64 | IStore, | 64 | IStore, |
1312 | 65 | ) | 65 | ) |
1313 | 66 | from lp.services.database.sqlbase import quote | 66 | from lp.services.database.sqlbase import quote |
1314 | @@ -1388,13 +1388,13 @@ class TranslationImportQueue: | |||
1315 | 1388 | 1388 | ||
1316 | 1389 | return approved_entries | 1389 | return approved_entries |
1317 | 1390 | 1390 | ||
1320 | 1391 | def _getSlaveStore(self): | 1391 | def _getStandbyStore(self): |
1321 | 1392 | """Return the slave store for the import queue. | 1392 | """Return the standby store for the import queue. |
1322 | 1393 | 1393 | ||
1323 | 1394 | Tests can override this to avoid unnecessary synchronization | 1394 | Tests can override this to avoid unnecessary synchronization |
1324 | 1395 | issues. | 1395 | issues. |
1325 | 1396 | """ | 1396 | """ |
1327 | 1397 | return ISlaveStore(TranslationImportQueueEntry) | 1397 | return IStandbyStore(TranslationImportQueueEntry) |
1328 | 1398 | 1398 | ||
1329 | 1399 | def _getBlockableDirectories(self): | 1399 | def _getBlockableDirectories(self): |
1330 | 1400 | """Describe all directories where uploads are to be blocked. | 1400 | """Describe all directories where uploads are to be blocked. |
1331 | @@ -1415,7 +1415,7 @@ class TranslationImportQueue: | |||
1332 | 1415 | """ | 1415 | """ |
1333 | 1416 | importer = getUtility(ITranslationImporter) | 1416 | importer = getUtility(ITranslationImporter) |
1334 | 1417 | 1417 | ||
1336 | 1418 | store = self._getSlaveStore() | 1418 | store = self._getStandbyStore() |
1337 | 1419 | TIQE = TranslationImportQueueEntry | 1419 | TIQE = TranslationImportQueueEntry |
1338 | 1420 | result = store.find( | 1420 | result = store.find( |
1339 | 1421 | (TIQE.distroseries_id, TIQE.sourcepackagename_id, | 1421 | (TIQE.distroseries_id, TIQE.sourcepackagename_id, |
1340 | diff --git a/lib/lp/translations/model/vpoexport.py b/lib/lp/translations/model/vpoexport.py | |||
1341 | index 4e1f730..11b7c1a 100644 | |||
1342 | --- a/lib/lp/translations/model/vpoexport.py | |||
1343 | +++ b/lib/lp/translations/model/vpoexport.py | |||
1344 | @@ -70,7 +70,7 @@ class VPOExportSet: | |||
1345 | 70 | if languagepack: | 70 | if languagepack: |
1346 | 71 | conditions.append(POTemplate.languagepack == True) | 71 | conditions.append(POTemplate.languagepack == True) |
1347 | 72 | 72 | ||
1349 | 73 | # Use the slave store. We may want to write to the distroseries | 73 | # Use the standby store. We may want to write to the distroseries |
1350 | 74 | # to register a language pack, but not to the translation data | 74 | # to register a language pack, but not to the translation data |
1351 | 75 | # we retrieve for it. | 75 | # we retrieve for it. |
1352 | 76 | # XXX wgrant 2017-03-21: Moved to master to avoid termination | 76 | # XXX wgrant 2017-03-21: Moved to master to avoid termination |
1353 | diff --git a/lib/lp/translations/scripts/tests/test_translations_to_branch.py b/lib/lp/translations/scripts/tests/test_translations_to_branch.py | |||
1354 | index ae6c1c2..e99e417 100644 | |||
1355 | --- a/lib/lp/translations/scripts/tests/test_translations_to_branch.py | |||
1356 | +++ b/lib/lp/translations/scripts/tests/test_translations_to_branch.py | |||
1357 | @@ -22,7 +22,7 @@ from lp.registry.interfaces.teammembership import ( | |||
1358 | 22 | ) | 22 | ) |
1359 | 23 | from lp.registry.model.productseries import ProductSeries | 23 | from lp.registry.model.productseries import ProductSeries |
1360 | 24 | from lp.services.config import config | 24 | from lp.services.config import config |
1362 | 25 | from lp.services.database.interfaces import ISlaveStore | 25 | from lp.services.database.interfaces import IStandbyStore |
1363 | 26 | from lp.services.log.logger import BufferLogger | 26 | from lp.services.log.logger import BufferLogger |
1364 | 27 | from lp.services.scripts.tests import run_script | 27 | from lp.services.scripts.tests import run_script |
1365 | 28 | from lp.testing import ( | 28 | from lp.testing import ( |
1366 | @@ -162,11 +162,11 @@ class TestExportTranslationsToBranch(TestCaseWithFactory): | |||
1367 | 162 | self.assertNotEqual( | 162 | self.assertNotEqual( |
1368 | 163 | db_branch.last_mirrored_id, | 163 | db_branch.last_mirrored_id, |
1369 | 164 | six.ensure_text(tree.branch.last_revision())) | 164 | six.ensure_text(tree.branch.last_revision())) |
1371 | 165 | # The export code works on a Branch from the slave store. It | 165 | # The export code works on a Branch from the standby store. It |
1372 | 166 | # shouldn't stop the scan request. | 166 | # shouldn't stop the scan request. |
1374 | 167 | slave_series = ISlaveStore(productseries).get( | 167 | standby_series = IStandbyStore(productseries).get( |
1375 | 168 | ProductSeries, productseries.id) | 168 | ProductSeries, productseries.id) |
1377 | 169 | exporter._exportToBranch(slave_series) | 169 | exporter._exportToBranch(standby_series) |
1378 | 170 | self.assertEqual( | 170 | self.assertEqual( |
1379 | 171 | db_branch.last_mirrored_id, | 171 | db_branch.last_mirrored_id, |
1380 | 172 | six.ensure_text(tree.branch.last_revision())) | 172 | six.ensure_text(tree.branch.last_revision())) |
1381 | diff --git a/lib/lp/translations/scripts/translations_to_branch.py b/lib/lp/translations/scripts/translations_to_branch.py | |||
1382 | index 92f5ca4..c3ef20b 100644 | |||
1383 | --- a/lib/lp/translations/scripts/translations_to_branch.py | |||
1384 | +++ b/lib/lp/translations/scripts/translations_to_branch.py | |||
1385 | @@ -39,7 +39,7 @@ from lp.codehosting.vfs import get_rw_server | |||
1386 | 39 | from lp.services.config import config | 39 | from lp.services.config import config |
1387 | 40 | from lp.services.database.interfaces import ( | 40 | from lp.services.database.interfaces import ( |
1388 | 41 | IMasterStore, | 41 | IMasterStore, |
1390 | 42 | ISlaveStore, | 42 | IStandbyStore, |
1391 | 43 | ) | 43 | ) |
1392 | 44 | from lp.services.helpers import shortlist | 44 | from lp.services.helpers import shortlist |
1393 | 45 | from lp.services.mail.helpers import ( | 45 | from lp.services.mail.helpers import ( |
1394 | @@ -312,7 +312,7 @@ class ExportTranslationsToBranch(LaunchpadCronScript): | |||
1395 | 312 | 312 | ||
1396 | 313 | self.logger.info("Exporting to translations branches.") | 313 | self.logger.info("Exporting to translations branches.") |
1397 | 314 | 314 | ||
1399 | 315 | self.store = ISlaveStore(Product) | 315 | self.store = IStandbyStore(Product) |
1400 | 316 | 316 | ||
1401 | 317 | product_join = Join( | 317 | product_join = Join( |
1402 | 318 | ProductSeries, Product, ProductSeries.product == Product.id) | 318 | ProductSeries, Product, ProductSeries.product == Product.id) |
1403 | diff --git a/lib/lp/translations/tests/test_autoapproval.py b/lib/lp/translations/tests/test_autoapproval.py | |||
1404 | index b778fac..b567c9d 100644 | |||
1405 | --- a/lib/lp/translations/tests/test_autoapproval.py | |||
1406 | +++ b/lib/lp/translations/tests/test_autoapproval.py | |||
1407 | @@ -1154,9 +1154,9 @@ class TestAutoBlocking(TestCaseWithFactory): | |||
1408 | 1154 | super().setUp() | 1154 | super().setUp() |
1409 | 1155 | self.queue = TranslationImportQueue() | 1155 | self.queue = TranslationImportQueue() |
1410 | 1156 | # Our test queue operates on the master store instead of the | 1156 | # Our test queue operates on the master store instead of the |
1412 | 1157 | # slave store so we don't have to synchronize stores. | 1157 | # standby store so we don't have to synchronize stores. |
1413 | 1158 | master_store = IMasterStore(TranslationImportQueueEntry) | 1158 | master_store = IMasterStore(TranslationImportQueueEntry) |
1415 | 1159 | self.queue._getSlaveStore = FakeMethod(result=master_store) | 1159 | self.queue._getStandbyStore = FakeMethod(result=master_store) |
1416 | 1160 | 1160 | ||
1417 | 1161 | def _copyTargetFromEntry(self, entry): | 1161 | def _copyTargetFromEntry(self, entry): |
1418 | 1162 | """Return a dict representing `entry`'s translation target. | 1162 | """Return a dict representing `entry`'s translation target. |
1419 | diff --git a/lib/lp/translations/tests/test_translationimportqueue.py b/lib/lp/translations/tests/test_translationimportqueue.py | |||
1420 | index 671195a..06abfdb 100644 | |||
1421 | --- a/lib/lp/translations/tests/test_translationimportqueue.py | |||
1422 | +++ b/lib/lp/translations/tests/test_translationimportqueue.py | |||
1423 | @@ -12,7 +12,7 @@ from zope.security.proxy import removeSecurityProxy | |||
1424 | 12 | from lp.app.enums import InformationType | 12 | from lp.app.enums import InformationType |
1425 | 13 | from lp.app.interfaces.launchpad import ILaunchpadCelebrities | 13 | from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
1426 | 14 | from lp.services.database.interfaces import ( | 14 | from lp.services.database.interfaces import ( |
1428 | 15 | ISlaveStore, | 15 | IStandbyStore, |
1429 | 16 | IStore, | 16 | IStore, |
1430 | 17 | ) | 17 | ) |
1431 | 18 | from lp.services.librarianserver.testing.fake import FakeLibrarian | 18 | from lp.services.librarianserver.testing.fake import FakeLibrarian |
1432 | @@ -484,14 +484,14 @@ class TestTranslationImportQueue(TestCaseWithFactory): | |||
1433 | 484 | # reshuffled to see if reportApprovalConflict can be fooled into | 484 | # reshuffled to see if reportApprovalConflict can be fooled into |
1434 | 485 | # thinking it's a different error. Make as sure as we can that | 485 | # thinking it's a different error. Make as sure as we can that |
1435 | 486 | # entry.error_output is not modified. | 486 | # entry.error_output is not modified. |
1437 | 487 | slave_entry = ISlaveStore(entry).get( | 487 | standby_entry = IStandbyStore(entry).get( |
1438 | 488 | TranslationImportQueueEntry, entry.id) | 488 | TranslationImportQueueEntry, entry.id) |
1441 | 489 | slave_entry.setErrorOutput = FakeMethod() | 489 | standby_entry.setErrorOutput = FakeMethod() |
1442 | 490 | slave_entry.reportApprovalConflict( | 490 | standby_entry.reportApprovalConflict( |
1443 | 491 | domain, len(templates), reversed(templates)) | 491 | domain, len(templates), reversed(templates)) |
1445 | 492 | self.assertEqual(original_error, slave_entry.error_output) | 492 | self.assertEqual(original_error, standby_entry.error_output) |
1446 | 493 | self.assertIn(domain, original_error) | 493 | self.assertIn(domain, original_error) |
1448 | 494 | self.assertEqual(0, slave_entry.setErrorOutput.call_count) | 494 | self.assertEqual(0, standby_entry.setErrorOutput.call_count) |
1449 | 495 | 495 | ||
1450 | 496 | 496 | ||
1451 | 497 | class TestHelpers(TestCaseWithFactory): | 497 | class TestHelpers(TestCaseWithFactory): |
1452 | diff --git a/scripts/get-stacked-on-branches.py b/scripts/get-stacked-on-branches.py | |||
1453 | index 9a60b7f..6c15bc0 100755 | |||
1454 | --- a/scripts/get-stacked-on-branches.py | |||
1455 | +++ b/scripts/get-stacked-on-branches.py | |||
1456 | @@ -27,7 +27,7 @@ from optparse import OptionParser | |||
1457 | 27 | 27 | ||
1458 | 28 | from storm.locals import Not | 28 | from storm.locals import Not |
1459 | 29 | 29 | ||
1461 | 30 | from lp.services.database.interfaces import ISlaveStore | 30 | from lp.services.database.interfaces import IStandbyStore |
1462 | 31 | from lp.services.scripts import execute_zcml_for_scripts | 31 | from lp.services.scripts import execute_zcml_for_scripts |
1463 | 32 | 32 | ||
1464 | 33 | 33 | ||
1465 | @@ -35,7 +35,7 @@ def get_stacked_branches(): | |||
1466 | 35 | """Iterate over all branches that, according to the db, are stacked.""" | 35 | """Iterate over all branches that, according to the db, are stacked.""" |
1467 | 36 | # Avoiding circular import. | 36 | # Avoiding circular import. |
1468 | 37 | from lp.code.model.branch import Branch | 37 | from lp.code.model.branch import Branch |
1470 | 38 | return ISlaveStore(Branch).find(Branch, Not(Branch.stacked_on == None)) | 38 | return IStandbyStore(Branch).find(Branch, Not(Branch.stacked_on == None)) |
1471 | 39 | 39 | ||
1472 | 40 | 40 | ||
1473 | 41 | def main(): | 41 | def main(): |
1474 | diff --git a/utilities/soyuz-sampledata-setup.py b/utilities/soyuz-sampledata-setup.py | |||
1475 | index b8cb28e..cde53e9 100755 | |||
1476 | --- a/utilities/soyuz-sampledata-setup.py | |||
1477 | +++ b/utilities/soyuz-sampledata-setup.py | |||
1478 | @@ -40,7 +40,7 @@ from lp.registry.interfaces.series import SeriesStatus | |||
1479 | 40 | from lp.registry.model.codeofconduct import SignedCodeOfConduct | 40 | from lp.registry.model.codeofconduct import SignedCodeOfConduct |
1480 | 41 | from lp.services.database.interfaces import ( | 41 | from lp.services.database.interfaces import ( |
1481 | 42 | IMasterStore, | 42 | IMasterStore, |
1483 | 43 | ISlaveStore, | 43 | IStandbyStore, |
1484 | 44 | ) | 44 | ) |
1485 | 45 | from lp.services.scripts.base import LaunchpadScript | 45 | from lp.services.scripts.base import LaunchpadScript |
1486 | 46 | from lp.soyuz.enums import SourcePackageFormat | 46 | from lp.soyuz.enums import SourcePackageFormat |
1487 | @@ -78,7 +78,7 @@ def check_preconditions(options): | |||
1488 | 78 | This script must not run on a production server, or anything | 78 | This script must not run on a production server, or anything |
1489 | 79 | remotely like it. | 79 | remotely like it. |
1490 | 80 | """ | 80 | """ |
1492 | 81 | store = ISlaveStore(ComponentSelection) | 81 | store = IStandbyStore(ComponentSelection) |
1493 | 82 | 82 | ||
1494 | 83 | # Just a guess, but dev systems aren't likely to have ids this high | 83 | # Just a guess, but dev systems aren't likely to have ids this high |
1495 | 84 | # in this table. Production data does. | 84 | # in this table. Production data does. |
LGTM