def test_repeater_failed_sends(self): """ This tests records that fail to send three times """ def now(): return datetime.utcnow() repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: with patch( 'corehq.apps.repeaters.models.simple_post_with_cached_timeout', return_value=MockResponse(status_code=404)) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 3) repeat_record.save() next_check_time = now() + timedelta(minutes=60) repeat_records = RepeatRecord.all( domain=self.domain, due_before=now() + timedelta(minutes=15), ) self.assertEqual(len(repeat_records), 0) repeat_records = RepeatRecord.all( domain=self.domain, due_before=next_check_time, ) self.assertEqual(len(repeat_records), 2)
def test_repeater_failed_sends(self): """ This tests records that fail are requeued later """ def now(): return datetime.utcnow() repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: with patch( 'corehq.apps.repeaters.models.simple_post', return_value=MockResponse(status_code=404, reason='Not Found')) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 1) next_check_time = now() + timedelta(minutes=60) repeat_records = RepeatRecord.all( domain=self.domain, due_before=now() + timedelta(minutes=15), ) self.assertEqual(len(repeat_records), 0) repeat_records = RepeatRecord.all( domain=self.domain, due_before=next_check_time, ) self.assertEqual(len(repeat_records), 2)
def test_repeater_successful_send(self): repeat_records = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) for repeat_record in repeat_records: with patch( 'corehq.apps.repeaters.models.simple_post', return_value=MockResponse(status_code=200, reason='No Reason')) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 1) mock_post.assert_any_call( repeat_record.get_payload(), repeat_record.repeater.get_url(repeat_record), headers=repeat_record.repeater.get_headers(repeat_record), timeout=POST_TIMEOUT, auth=repeat_record.repeater.get_auth(), ) # The following is pretty fickle and depends on which of # - corehq.apps.repeaters.signals # - casexml.apps.case.signals # gets loaded first. # This is deterministic but easily affected by minor code changes repeat_records = RepeatRecord.all( domain=self.domain, due_before=datetime.utcnow(), ) for repeat_record in repeat_records: self.assertEqual(repeat_record.succeeded, True) self.assertEqual(repeat_record.next_check, None) self.assertEqual(len(self.repeat_records(self.domain)), 0) self.post_xml(self.update_xform_xml, self.domain) self.assertEqual(len(self.repeat_records(self.domain)), 2)
def test_repeat_record_status_check(self): self.assertEqual(len(RepeatRecord.all()), 2) # Do not trigger cancelled records for repeat_record in RepeatRecord.all(): repeat_record.cancelled = True repeat_record.save() with patch('corehq.apps.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) # trigger force send records if not cancelled and tries not exhausted for repeat_record in RepeatRecord.all(): with patch('corehq.apps.repeaters.models.simple_post', return_value=MockResponse(status_code=200, reason='') ) as mock_fire: repeat_record.fire(force_send=True) self.assertEqual(mock_fire.call_count, 1) # all records should be in SUCCESS state after force try for repeat_record in RepeatRecord.all(): self.assertEqual(repeat_record.state, RECORD_SUCCESS_STATE) self.assertEqual(repeat_record.overall_tries, 1) # not trigger records succeeded triggered after cancellation with patch('corehq.apps.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) for repeat_record in RepeatRecord.all(): self.assertEqual(repeat_record.state, RECORD_SUCCESS_STATE)
def test_repeat_record_created(self): ''' Tests that whenever an application with a repeater is saved that a repeat record is created. ''' application = Application(domain=self.domain) application.save() repeat_records = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) self.assertEqual(len(repeat_records), 0) app_structure_repeater = AppStructureRepeater(domain=self.domain, url=self.forwarding_url) app_structure_repeater.save() application.save() repeat_records = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) self.assertEqual(len(repeat_records), 1) for repeat_record in repeat_records: self.assertEqual(repeat_record.url, self.forwarding_url) self.assertEqual(repeat_record.get_payload(), application.get_id) repeat_record.delete() application.delete() app_structure_repeater.delete()
def test_skip_device_logs(self): devicelog_xml = XFORM_XML_TEMPLATE.format(DEVICE_LOG_XMLNS, USER_ID, '1234', '') self.post_xml(devicelog_xml, self.domain) repeat_records = RepeatRecord.all(domain=self.domain) for repeat_record in repeat_records: self.assertNotEqual(repeat_record.payload_id, '1234')
def tearDown(self): self.case_repeater.delete() self.form_repeater.delete() XFormInstance.get(instance_id).delete() repeat_records = RepeatRecord.all() for repeat_record in repeat_records: repeat_record.delete()
def check_repeaters(request, domain): if request.method == 'GET': return HttpResponse(PAGE % {'status': '', 'domain': domain}) elif request.method == 'POST': start = datetime.utcnow() repeat_records = RepeatRecord.all(domain, due_before=start, limit=100) process_repeater_list(repeat_records) return HttpResponse(PAGE % {'status': 'Done', 'domain': domain})
def test_process_repeat_record_locking(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.apps.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2) with patch('corehq.apps.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 0) records = RepeatRecord.all() # Saving should unlock them again by changing the rev for record in records: record.save() with patch('corehq.apps.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2)
def test_check_repeat_records(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.apps.repeaters.models.simple_post_with_cached_timeout') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 2) with patch('corehq.apps.repeaters.models.simple_post_with_cached_timeout') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0)
def test_ignore_document(self): """ When get_payload raises IgnoreDocument, fire should call update_success """ repeat_records = RepeatRecord.all(domain=self.domain, ) for repeat_record_ in repeat_records: repeat_record_.fire() self.assertIsNone(repeat_record_.next_check) self.assertTrue(repeat_record_.succeeded)
def test_check_repeat_records(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.apps.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 2) with patch('corehq.apps.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0)
def handle(self, *args, **options): if len(args) == 1: domain = args[0] else: raise CommandError('Usage: %s\n%s' % (self.args, self.help)) next_year = datetime.datetime.utcnow() + datetime.timedelta(days=365) records = RepeatRecord.all(domain=domain, due_before=next_year) for record in records: record.fire(post_fn=simple_post) print('{} {}'.format( record._id, 'successful' if record.succeeded else 'failed'))
def handle(self, *args, **options): if len(args) == 1: domain = args[0] else: raise CommandError('Usage: %s\n%s' % (self.args, self.help)) next_year = datetime.datetime.utcnow() + datetime.timedelta(days=365) records = RepeatRecord.all(domain=domain, due_before=next_year) for record in records: record.fire(post_fn=simple_post) record.save() print '{} {}'.format(record._id, 'successful' if record.succeeded else 'failed')
def test_ignore_document(self): """ When get_payload raises IgnoreDocument, fire should call update_success """ repeat_records = RepeatRecord.all( domain=self.domain, ) for repeat_record_ in repeat_records: repeat_record_.fire() self.assertIsNone(repeat_record_.next_check) self.assertTrue(repeat_record_.succeeded)
def test_repeater_successful_send(self): repeat_records = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) mocked_responses = [ MockResponse(status_code=404, reason='Not Found'), MockResponse(status_code=200, reason='No Reason') ] for repeat_record in repeat_records: with patch( 'corehq.apps.repeaters.models.simple_post_with_cached_timeout', side_effect=mocked_responses) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 2) mock_post.assert_any_call( repeat_record.get_payload(), repeat_record.repeater.get_url(repeat_record), headers=repeat_record.repeater.get_headers(repeat_record), force_send=False, timeout=POST_TIMEOUT, ) repeat_record.save() # The following is pretty fickle and depends on which of # - corehq.apps.repeaters.signals # - casexml.apps.case.signals # gets loaded first. # This is deterministic but easily affected by minor code changes repeat_records = RepeatRecord.all( domain=self.domain, due_before=datetime.utcnow(), ) for repeat_record in repeat_records: self.assertEqual(repeat_record.succeeded, True) self.assertEqual(repeat_record.next_check, None) self.assertEqual(len(self.repeat_records(self.domain)), 0) self.post_xml(self.update_xform_xml, self.domain) self.assertEqual(len(self.repeat_records(self.domain)), 2)
def loop(): # take LIMIT records off the top # the assumption is that they all get 'popped' in the for loop # the only exception I can see is if there's a problem with the # locking, a large number of locked tasks could pile up at the top, # so make a provision for that worst case number_locked = progress_report['number_locked'] repeat_records = RepeatRecord.all( due_before=start, limit=LIMIT + number_locked ) return process_repeater_list( repeat_records, start=start, cutoff=start + CHECK_REPEATERS_INTERVAL, progress_report=progress_report )
def test_ignore_document(self): """ When get_payload raises IgnoreDocument, fire should call update_success """ @RegisterGenerator(FormRepeater, 'new_format', 'XML') class NewFormGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): raise IgnoreDocument repeat_records = RepeatRecord.all( domain=self.domain, ) for repeat_record_ in repeat_records: repeat_record_.fire() self.assertIsNone(repeat_record_.next_check) self.assertTrue(repeat_record_.succeeded)
def handle(self, domain, **options): next_year = datetime.datetime.utcnow() + datetime.timedelta(days=365) records = RepeatRecord.all(domain=domain, due_before=next_year) for record in records: record.fire(post_fn=simple_post) print('{} {}'.format(record._id, 'successful' if record.succeeded else 'failed'))
def test_skip_device_logs(self): devicelog_xml = xform_xml_template.format(DEVICE_LOG_XMLNS, '1234', '') self.post_xml(devicelog_xml, self.domain) repeat_records = RepeatRecord.all(domain=self.domain) for repeat_record in repeat_records: self.assertNotEqual(repeat_record.payload_id, '1234')
def repeat_records(self): return RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow())
def tearDown(self): self.repeater.delete() repeat_records = RepeatRecord.all() for repeat_record in repeat_records: repeat_record.delete()
def test_repeater(self): # this test should probably be divided into more units CommCareCase.get(case_id) def now(): return datetime.utcnow() repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2) self.clear_log() records_by_repeater_id = {} for repeat_record in repeat_records: repeat_record.fire(post_fn=self.make_post_fn([404, 404, 404])) repeat_record.save() records_by_repeater_id[repeat_record.repeater_id] = repeat_record for (url, status, data, headers) in self.log: self.assertEqual(status, 404) self.clear_log() next_check_time = now() + timedelta(minutes=60) repeat_records = RepeatRecord.all( domain=self.domain, due_before=now() + timedelta(minutes=15), ) self.assertEqual(len(repeat_records), 0) repeat_records = RepeatRecord.all( domain=self.domain, due_before=next_check_time + timedelta(seconds=2), ) self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: self.assertLess(abs(next_check_time - repeat_record.next_check), timedelta(seconds=3)) repeat_record.fire(post_fn=self.make_post_fn([404, 200])) repeat_record.save() self.assertEqual(len(self.log), 4) # The following is pretty fickle and depends on which of # - corehq.apps.repeaters.signals # - casexml.apps.case.signals # gets loaded first. # This is deterministic but easily affected by minor code changes # check case stuff rec = records_by_repeater_id[self.case_repeater.get_id] self.assertEqual(self.log[1][:2], (self.case_repeater.get_url(rec), 200)) self.assertIn('server-modified-on', self.log[1][3]) check_xml_line_by_line(self, self.log[1][2], case_block) # check form stuff rec = records_by_repeater_id[self.form_repeater.get_id] self.assertEqual(self.log[3][:3], (self.form_repeater.get_url(rec), 200, xform_xml)) self.assertIn('received-on', self.log[3][3]) repeat_records = RepeatRecord.all( domain=self.domain, due_before=next_check_time, ) for repeat_record in repeat_records: self.assertEqual(repeat_record.succeeded, True) self.assertEqual(repeat_record.next_check, None) self.assertEqual(len(self.repeat_records(self.domain)), 0) self.post_xml(update_xform_xml, self.domain) self.assertEqual(len(self.repeat_records(self.domain)), 2)
def repeat_records(cls, domain_name): return RepeatRecord.all(domain=domain_name, due_before=datetime.utcnow())