116
119
raise RaisingJobException('oops notifying users')
122
class RetryError(Exception):
126
class RaisingRetryJob(NullJob):
128
retry_error_types = (RetryError,)
119
136
class TestJobRunner(TestCaseWithFactory):
120
137
"""Ensure JobRunner behaves as expected."""
161
178
def test_runAll_reports_oopses(self):
162
179
"""When an error is encountered, report an oops and continue."""
163
180
job_1, job_2 = self.makeTwoJobs()
164
182
def raiseError():
165
183
# Ensure that jobs which call transaction.abort work, too.
166
184
transaction.abort()
181
199
def test_oops_messages_used_when_handling(self):
182
200
"""Oops messages should appear even when exceptions are handled."""
183
201
job_1, job_2 = self.makeTwoJobs()
184
203
def handleError():
185
204
reporter = errorlog.globalErrorUtility
216
235
def test_runAll_mails_oopses(self):
217
236
"""Email interested parties about OOPses."""
218
237
job_1, job_2 = self.makeTwoJobs()
219
239
def raiseError():
220
240
# Ensure that jobs which call transaction.abort work, too.
221
241
transaction.abort()
243
263
error messages are mailed to interested parties verbatim.
245
265
job_1, job_2 = self.makeTwoJobs()
246
267
class ExampleError(Exception):
248
270
def raiseError():
249
271
raise ExampleError('Fake exception. Foobar, I say!')
250
272
job_1.run = raiseError
301
324
runner.runJobHandleError(job)
302
325
self.assertEqual(0, len(self.oopses))
327
def test_runJob_raising_retry_error(self):
328
"""If a job raises a retry_error, it should be re-queued."""
329
job = RaisingRetryJob('completion')
330
runner = JobRunner([job])
331
with self.expectedLog('Scheduling retry due to RetryError'):
333
self.assertEqual(JobStatus.WAITING, job.status)
334
self.assertNotIn(job, runner.completed_jobs)
335
self.assertIn(job, runner.incomplete_jobs)
337
def test_runJob_exceeding_max_retries(self):
338
"""If a job exceeds maximum retries, it should raise normally."""
339
job = RaisingRetryJob('completion')
340
JobRunner([job]).runJob(job)
341
self.assertEqual(JobStatus.WAITING, job.status)
342
runner = JobRunner([job])
343
with self.expectedLog('Job execution raised an exception.'):
344
with ExpectedException(RetryError, ''):
346
self.assertEqual(JobStatus.FAILED, job.status)
347
self.assertNotIn(job, runner.completed_jobs)
348
self.assertIn(job, runner.incomplete_jobs)
304
350
def test_runJobHandleErrors_oops_generated_notify_fails(self):
305
351
"""A second oops is logged if the notification of the oops fails."""
306
352
job = RaisingJobRaisingNotifyOops('boom')
319
365
runner.runJobHandleError(job)
320
366
self.assertEqual(1, len(self.oopses))
368
def test_runJob_with_SuspendJobException(self):
369
# A job that raises SuspendJobError should end up suspended.
370
job = NullJob('suspended')
371
job.run = FakeMethod(failure=SuspendJobException())
372
runner = JobRunner([job])
375
self.assertEqual(JobStatus.SUSPENDED, job.status)
376
self.assertNotIn(job, runner.completed_jobs)
377
self.assertIn(job, runner.incomplete_jobs)
323
380
class StuckJob(BaseRunnableJob):
324
381
"""Simulation of a job that stalls."""