Merge lp:~cjwatson/launchpad/snap-store-upload-job-commit into lp:launchpad
- snap-store-upload-job-commit
- Merge into devel
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 18995 |
Proposed branch: | lp:~cjwatson/launchpad/snap-store-upload-job-commit |
Merge into: | lp:launchpad |
Diff against target: |
277 lines (+71/-52) 2 files modified
lib/lp/snappy/model/snapbuildjob.py (+43/-36) lib/lp/snappy/tests/test_snapbuildjob.py (+28/-16) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad/snap-store-upload-job-commit |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+369243@code.launchpad.net |
Commit message
Consistently commit transactions in SnapStoreUploadJob.
Description of the change
We were previously ensuring that the transaction is committed when the job fails, but not when raising a retryable exception or after sending event notifications. The latter case caused some webhook deliveries not to be sent.
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/snappy/model/snapbuildjob.py' | |||
2 | --- lib/lp/snappy/model/snapbuildjob.py 2019-06-19 14:04:34 +0000 | |||
3 | +++ lib/lp/snappy/model/snapbuildjob.py 2019-06-24 12:07:53 +0000 | |||
4 | @@ -1,4 +1,4 @@ | |||
6 | 1 | # Copyright 2016-2017 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2016-2019 Canonical Ltd. This software is licensed under the |
7 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
8 | 3 | 3 | ||
9 | 4 | """Snap build jobs.""" | 4 | """Snap build jobs.""" |
10 | @@ -280,11 +280,15 @@ | |||
11 | 280 | # Ideally we'd just override Job._set_status or similar, but | 280 | # Ideally we'd just override Job._set_status or similar, but |
12 | 281 | # lazr.delegates makes that difficult, so we use this to override all | 281 | # lazr.delegates makes that difficult, so we use this to override all |
13 | 282 | # the individual Job lifecycle methods instead. | 282 | # the individual Job lifecycle methods instead. |
15 | 283 | def _do_lifecycle(self, method_name, *args, **kwargs): | 283 | def _do_lifecycle(self, method_name, manage_transaction=False, |
16 | 284 | *args, **kwargs): | ||
17 | 284 | old_store_upload_status = self.snapbuild.store_upload_status | 285 | old_store_upload_status = self.snapbuild.store_upload_status |
19 | 285 | getattr(super(SnapStoreUploadJob, self), method_name)(*args, **kwargs) | 286 | getattr(super(SnapStoreUploadJob, self), method_name)( |
20 | 287 | *args, manage_transaction=manage_transaction, **kwargs) | ||
21 | 286 | if self.snapbuild.store_upload_status != old_store_upload_status: | 288 | if self.snapbuild.store_upload_status != old_store_upload_status: |
22 | 287 | notify(SnapBuildStoreUploadStatusChangedEvent(self.snapbuild)) | 289 | notify(SnapBuildStoreUploadStatusChangedEvent(self.snapbuild)) |
23 | 290 | if manage_transaction: | ||
24 | 291 | transaction.commit() | ||
25 | 288 | 292 | ||
26 | 289 | def start(self, *args, **kwargs): | 293 | def start(self, *args, **kwargs): |
27 | 290 | self._do_lifecycle("start", *args, **kwargs) | 294 | self._do_lifecycle("start", *args, **kwargs) |
28 | @@ -329,39 +333,42 @@ | |||
29 | 329 | """See `IRunnableJob`.""" | 333 | """See `IRunnableJob`.""" |
30 | 330 | client = getUtility(ISnapStoreClient) | 334 | client = getUtility(ISnapStoreClient) |
31 | 331 | try: | 335 | try: |
65 | 332 | if "status_url" not in self.store_metadata: | 336 | try: |
66 | 333 | self.status_url = client.upload(self.snapbuild) | 337 | if "status_url" not in self.store_metadata: |
67 | 334 | # We made progress, so reset attempt_count. | 338 | self.status_url = client.upload(self.snapbuild) |
68 | 335 | self.attempt_count = 1 | 339 | # We made progress, so reset attempt_count. |
69 | 336 | if self.store_url is None: | 340 | self.attempt_count = 1 |
70 | 337 | # This is no longer strictly necessary as the store is handling | 341 | if self.store_url is None: |
71 | 338 | # releases via the release intent, but we export various fields | 342 | # This is no longer strictly necessary as the store is |
72 | 339 | # via the api, so once this is called, we're done with | 343 | # handling releases via the release intent, but we |
73 | 340 | # this task | 344 | # export various fields via the API, so once this is |
74 | 341 | self.store_url, self.store_revision = ( | 345 | # called, we're done with this task. |
75 | 342 | client.checkStatus(self.status_url)) | 346 | self.store_url, self.store_revision = ( |
76 | 343 | self.error_message = None | 347 | client.checkStatus(self.status_url)) |
77 | 344 | except self.retry_error_types: | 348 | self.error_message = None |
78 | 345 | raise | 349 | except self.retry_error_types: |
79 | 346 | except Exception as e: | 350 | raise |
80 | 347 | if (isinstance(e, SnapStoreError) and e.can_retry and | 351 | except Exception as e: |
81 | 348 | self.attempt_count <= self.max_retries): | 352 | if (isinstance(e, SnapStoreError) and e.can_retry and |
82 | 349 | raise RetryableSnapStoreError(e.message, detail=e.detail) | 353 | self.attempt_count <= self.max_retries): |
83 | 350 | self.error_message = str(e) | 354 | raise RetryableSnapStoreError(e.message, detail=e.detail) |
84 | 351 | self.error_messages = getattr(e, "messages", None) | 355 | self.error_message = str(e) |
85 | 352 | self.error_detail = getattr(e, "detail", None) | 356 | self.error_messages = getattr(e, "messages", None) |
86 | 353 | if isinstance(e, UnauthorizedUploadResponse): | 357 | self.error_detail = getattr(e, "detail", None) |
87 | 354 | mailer = SnapBuildMailer.forUnauthorizedUpload(self.snapbuild) | 358 | mailer_factory = None |
88 | 355 | mailer.sendAll() | 359 | if isinstance(e, UnauthorizedUploadResponse): |
89 | 356 | elif isinstance(e, BadRefreshResponse): | 360 | mailer_factory = SnapBuildMailer.forUnauthorizedUpload |
90 | 357 | mailer = SnapBuildMailer.forRefreshFailure(self.snapbuild) | 361 | elif isinstance(e, BadRefreshResponse): |
91 | 358 | mailer.sendAll() | 362 | mailer_factory = SnapBuildMailer.forRefreshFailure |
92 | 359 | elif isinstance(e, UploadFailedResponse): | 363 | elif isinstance(e, UploadFailedResponse): |
93 | 360 | mailer = SnapBuildMailer.forUploadFailure(self.snapbuild) | 364 | mailer_factory = SnapBuildMailer.forUploadFailure |
94 | 361 | mailer.sendAll() | 365 | elif isinstance(e, |
95 | 362 | elif isinstance(e, (BadScanStatusResponse, ScanFailedResponse)): | 366 | (BadScanStatusResponse, ScanFailedResponse)): |
96 | 363 | mailer = SnapBuildMailer.forUploadScanFailure(self.snapbuild) | 367 | mailer_factory = SnapBuildMailer.forUploadScanFailure |
97 | 364 | mailer.sendAll() | 368 | if mailer_factory is not None: |
98 | 369 | mailer_factory(self.snapbuild).sendAll() | ||
99 | 370 | raise | ||
100 | 371 | except Exception: | ||
101 | 365 | # The normal job infrastructure will abort the transaction, but | 372 | # The normal job infrastructure will abort the transaction, but |
102 | 366 | # we want to commit instead: the only database changes we make | 373 | # we want to commit instead: the only database changes we make |
103 | 367 | # are to this job's metadata and should be preserved. | 374 | # are to this job's metadata and should be preserved. |
104 | 368 | 375 | ||
105 | === modified file 'lib/lp/snappy/tests/test_snapbuildjob.py' | |||
106 | --- lib/lp/snappy/tests/test_snapbuildjob.py 2019-06-20 13:16:35 +0000 | |||
107 | +++ lib/lp/snappy/tests/test_snapbuildjob.py 2019-06-24 12:07:53 +0000 | |||
108 | @@ -17,6 +17,7 @@ | |||
109 | 17 | MatchesListwise, | 17 | MatchesListwise, |
110 | 18 | MatchesStructure, | 18 | MatchesStructure, |
111 | 19 | ) | 19 | ) |
112 | 20 | import transaction | ||
113 | 20 | from zope.interface import implementer | 21 | from zope.interface import implementer |
114 | 21 | from zope.security.proxy import removeSecurityProxy | 22 | from zope.security.proxy import removeSecurityProxy |
115 | 22 | 23 | ||
116 | @@ -58,6 +59,17 @@ | |||
117 | 58 | from lp.testing.mail_helpers import pop_notifications | 59 | from lp.testing.mail_helpers import pop_notifications |
118 | 59 | 60 | ||
119 | 60 | 61 | ||
120 | 62 | def run_isolated_jobs(jobs): | ||
121 | 63 | """Run a sequence of jobs, ensuring transaction isolation. | ||
122 | 64 | |||
123 | 65 | We abort the transaction after each job to make sure that there is no | ||
124 | 66 | relevant uncommitted work. | ||
125 | 67 | """ | ||
126 | 68 | for job in jobs: | ||
127 | 69 | JobRunner([job]).runAll() | ||
128 | 70 | transaction.abort() | ||
129 | 71 | |||
130 | 72 | |||
131 | 61 | @implementer(ISnapStoreClient) | 73 | @implementer(ISnapStoreClient) |
132 | 62 | class FakeSnapStoreClient: | 74 | class FakeSnapStoreClient: |
133 | 63 | 75 | ||
134 | @@ -161,7 +173,7 @@ | |||
135 | 161 | client.checkStatus.result = (self.store_url, 1) | 173 | client.checkStatus.result = (self.store_url, 1) |
136 | 162 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 174 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
137 | 163 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 175 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
139 | 164 | JobRunner([job]).runAll() | 176 | run_isolated_jobs([job]) |
140 | 165 | self.assertEqual([((snapbuild,), {})], client.upload.calls) | 177 | self.assertEqual([((snapbuild,), {})], client.upload.calls) |
141 | 166 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) | 178 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) |
142 | 167 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 179 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
143 | @@ -182,7 +194,7 @@ | |||
144 | 182 | client.upload.failure = ValueError("An upload failure") | 194 | client.upload.failure = ValueError("An upload failure") |
145 | 183 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 195 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
146 | 184 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 196 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
148 | 185 | JobRunner([job]).runAll() | 197 | run_isolated_jobs([job]) |
149 | 186 | self.assertEqual([((snapbuild,), {})], client.upload.calls) | 198 | self.assertEqual([((snapbuild,), {})], client.upload.calls) |
150 | 187 | self.assertEqual([], client.checkStatus.calls) | 199 | self.assertEqual([], client.checkStatus.calls) |
151 | 188 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 200 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
152 | @@ -208,7 +220,7 @@ | |||
153 | 208 | "Authorization failed.") | 220 | "Authorization failed.") |
154 | 209 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 221 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
155 | 210 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 222 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
157 | 211 | JobRunner([job]).runAll() | 223 | run_isolated_jobs([job]) |
158 | 212 | self.assertEqual([((snapbuild,), {})], client.upload.calls) | 224 | self.assertEqual([((snapbuild,), {})], client.upload.calls) |
159 | 213 | self.assertEqual([], client.checkStatus.calls) | 225 | self.assertEqual([], client.checkStatus.calls) |
160 | 214 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 226 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
161 | @@ -254,7 +266,7 @@ | |||
162 | 254 | "Proxy error", can_retry=True) | 266 | "Proxy error", can_retry=True) |
163 | 255 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 267 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
164 | 256 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 268 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
166 | 257 | JobRunner([job]).runAll() | 269 | run_isolated_jobs([job]) |
167 | 258 | self.assertEqual([((snapbuild,), {})], client.upload.calls) | 270 | self.assertEqual([((snapbuild,), {})], client.upload.calls) |
168 | 259 | self.assertEqual([], client.checkStatus.calls) | 271 | self.assertEqual([], client.checkStatus.calls) |
169 | 260 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 272 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
170 | @@ -272,7 +284,7 @@ | |||
171 | 272 | client.upload.result = self.status_url | 284 | client.upload.result = self.status_url |
172 | 273 | client.checkStatus.result = (self.store_url, 1) | 285 | client.checkStatus.result = (self.store_url, 1) |
173 | 274 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 286 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
175 | 275 | JobRunner([job]).runAll() | 287 | run_isolated_jobs([job]) |
176 | 276 | self.assertEqual([((snapbuild,), {})], client.upload.calls) | 288 | self.assertEqual([((snapbuild,), {})], client.upload.calls) |
177 | 277 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) | 289 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) |
178 | 278 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 290 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
179 | @@ -299,7 +311,7 @@ | |||
180 | 299 | client.upload.failure = BadRefreshResponse("SSO melted.") | 311 | client.upload.failure = BadRefreshResponse("SSO melted.") |
181 | 300 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 312 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
182 | 301 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 313 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
184 | 302 | JobRunner([job]).runAll() | 314 | run_isolated_jobs([job]) |
185 | 303 | self.assertEqual([((snapbuild,), {})], client.upload.calls) | 315 | self.assertEqual([((snapbuild,), {})], client.upload.calls) |
186 | 304 | self.assertEqual([], client.checkStatus.calls) | 316 | self.assertEqual([], client.checkStatus.calls) |
187 | 305 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 317 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
188 | @@ -350,7 +362,7 @@ | |||
189 | 350 | "Failed to upload", detail="The proxy exploded.\n") | 362 | "Failed to upload", detail="The proxy exploded.\n") |
190 | 351 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 363 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
191 | 352 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 364 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
193 | 353 | JobRunner([job]).runAll() | 365 | run_isolated_jobs([job]) |
194 | 354 | self.assertEqual([((snapbuild,), {})], client.upload.calls) | 366 | self.assertEqual([((snapbuild,), {})], client.upload.calls) |
195 | 355 | self.assertEqual([], client.checkStatus.calls) | 367 | self.assertEqual([], client.checkStatus.calls) |
196 | 356 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 368 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
197 | @@ -399,7 +411,7 @@ | |||
198 | 399 | client.checkStatus.failure = UploadNotScannedYetResponse() | 411 | client.checkStatus.failure = UploadNotScannedYetResponse() |
199 | 400 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 412 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
200 | 401 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 413 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
202 | 402 | JobRunner([job]).runAll() | 414 | run_isolated_jobs([job]) |
203 | 403 | self.assertEqual([((snapbuild,), {})], client.upload.calls) | 415 | self.assertEqual([((snapbuild,), {})], client.upload.calls) |
204 | 404 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) | 416 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) |
205 | 405 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 417 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
206 | @@ -417,7 +429,7 @@ | |||
207 | 417 | client.checkStatus.failure = None | 429 | client.checkStatus.failure = None |
208 | 418 | client.checkStatus.result = (self.store_url, 1) | 430 | client.checkStatus.result = (self.store_url, 1) |
209 | 419 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 431 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
211 | 420 | JobRunner([job]).runAll() | 432 | run_isolated_jobs([job]) |
212 | 421 | self.assertEqual([], client.upload.calls) | 433 | self.assertEqual([], client.upload.calls) |
213 | 422 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) | 434 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) |
214 | 423 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 435 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
215 | @@ -448,7 +460,7 @@ | |||
216 | 448 | {"message": "Confinement not allowed.", "link": "link2"}]) | 460 | {"message": "Confinement not allowed.", "link": "link2"}]) |
217 | 449 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 461 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
218 | 450 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 462 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
220 | 451 | JobRunner([job]).runAll() | 463 | run_isolated_jobs([job]) |
221 | 452 | self.assertEqual([((snapbuild,), {})], client.upload.calls) | 464 | self.assertEqual([((snapbuild,), {})], client.upload.calls) |
222 | 453 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) | 465 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) |
223 | 454 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 466 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
224 | @@ -497,7 +509,7 @@ | |||
225 | 497 | client.checkStatus.result = (self.store_url, 1) | 509 | client.checkStatus.result = (self.store_url, 1) |
226 | 498 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 510 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
227 | 499 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 511 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
229 | 500 | JobRunner([job]).runAll() | 512 | run_isolated_jobs([job]) |
230 | 501 | self.assertEqual([((snapbuild,), {})], client.upload.calls) | 513 | self.assertEqual([((snapbuild,), {})], client.upload.calls) |
231 | 502 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) | 514 | self.assertEqual([((self.status_url,), {})], client.checkStatus.calls) |
232 | 503 | self.assertContentEqual([job], snapbuild.store_upload_jobs) | 515 | self.assertContentEqual([job], snapbuild.store_upload_jobs) |
233 | @@ -520,7 +532,7 @@ | |||
234 | 520 | "Proxy error", can_retry=True) | 532 | "Proxy error", can_retry=True) |
235 | 521 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 533 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
236 | 522 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 534 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
238 | 523 | JobRunner([job]).runAll() | 535 | run_isolated_jobs([job]) |
239 | 524 | self.assertNotIn("status_url", job.metadata) | 536 | self.assertNotIn("status_url", job.metadata) |
240 | 525 | self.assertEqual(timedelta(seconds=60), job.retry_delay) | 537 | self.assertEqual(timedelta(seconds=60), job.retry_delay) |
241 | 526 | job.scheduled_start = None | 538 | job.scheduled_start = None |
242 | @@ -529,7 +541,7 @@ | |||
243 | 529 | client.checkStatus.failure = UploadNotScannedYetResponse() | 541 | client.checkStatus.failure = UploadNotScannedYetResponse() |
244 | 530 | for expected_delay in (15, 15, 30, 30, 60): | 542 | for expected_delay in (15, 15, 30, 30, 60): |
245 | 531 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 543 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
247 | 532 | JobRunner([job]).runAll() | 544 | run_isolated_jobs([job]) |
248 | 533 | self.assertIn("status_url", job.snapbuild.store_upload_metadata) | 545 | self.assertIn("status_url", job.snapbuild.store_upload_metadata) |
249 | 534 | self.assertIsNone(job.store_url) | 546 | self.assertIsNone(job.store_url) |
250 | 535 | self.assertEqual( | 547 | self.assertEqual( |
251 | @@ -538,7 +550,7 @@ | |||
252 | 538 | client.checkStatus.failure = None | 550 | client.checkStatus.failure = None |
253 | 539 | client.checkStatus.result = (self.store_url, 1) | 551 | client.checkStatus.result = (self.store_url, 1) |
254 | 540 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 552 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
256 | 541 | JobRunner([job]).runAll() | 553 | run_isolated_jobs([job]) |
257 | 542 | self.assertEqual(self.store_url, job.store_url) | 554 | self.assertEqual(self.store_url, job.store_url) |
258 | 543 | self.assertIsNone(job.error_message) | 555 | self.assertIsNone(job.error_message) |
259 | 544 | self.assertEqual([], pop_notifications()) | 556 | self.assertEqual([], pop_notifications()) |
260 | @@ -556,7 +568,7 @@ | |||
261 | 556 | client.checkStatus.result = (self.store_url, 1) | 568 | client.checkStatus.result = (self.store_url, 1) |
262 | 557 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) | 569 | self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) |
263 | 558 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 570 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
265 | 559 | JobRunner([job]).runAll() | 571 | run_isolated_jobs([job]) |
266 | 560 | 572 | ||
267 | 561 | previous_upload = client.upload.calls | 573 | previous_upload = client.upload.calls |
268 | 562 | previous_checkStatus = client.checkStatus.calls | 574 | previous_checkStatus = client.checkStatus.calls |
269 | @@ -570,7 +582,7 @@ | |||
270 | 570 | 582 | ||
271 | 571 | # Run the job again | 583 | # Run the job again |
272 | 572 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): | 584 | with dbuser(config.ISnapStoreUploadJobSource.dbuser): |
274 | 573 | JobRunner([job]).runAll() | 585 | run_isolated_jobs([job]) |
275 | 574 | 586 | ||
276 | 575 | # Release is not called due to release intent in upload | 587 | # Release is not called due to release intent in upload |
277 | 576 | # but ensure that we have not called upload twice | 588 | # but ensure that we have not called upload twice |