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.motech.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.motech.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.motech.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_repeater_failed_sends(self): """ This tests records that fail are requeued later """ def now(): return datetime.utcnow() repeat_records = self.repeat_records() self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: with patch( 'corehq.motech.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) # Enqueued repeat records have next_check incremented by 48 hours next_check_time = now() + timedelta(minutes=60) + timedelta(hours=48) 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_skip_duplicates(self): """ Ensure that submitting a duplicate form does not create extra RepeatRecords """ self.assertEqual(len(RepeatRecord.all()), 2) # this form is already submitted during setUp so a second submission should be a duplicate form = self.post_xml(self.xform_xml, self.domain).xform self.assertTrue(form.is_duplicate) self.assertEqual(len(RepeatRecord.all()), 2)
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, 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 handle(self, domain, **options): next_year = datetime.datetime.utcnow() + datetime.timedelta(days=365) records = RepeatRecord.all( domain=domain, due_before=next_year) # Excludes succeeded and cancelled for record in records: record.fire(force_send=True) print('{} {}'.format( record._id, 'successful' if record.succeeded else 'failed'))
def _run_test(self, event_type, expected_records_after_create, expected_records_after_update, case_type=ZAPIER_CASE_TYPE): ZapierSubscription.objects.create( domain=self.domain, user_id=str(self.web_user._id), event_name=event_type, url='http://example.com/lets-make-some-cases/', case_type=ZAPIER_CASE_TYPE, ) # create case and run checks case_id = uuid.uuid4().hex post_case_blocks([ CaseBlock.deprecated_init( create=True, case_id=case_id, case_type=case_type, ).as_xml() ], domain=self.domain) # Enqueued repeat records have next_check set 48 hours in the future. later = datetime.utcnow() + timedelta(hours=48 + 1) repeat_records = list( RepeatRecord.all(domain=self.domain, due_before=later)) self.assertEqual(expected_records_after_create, len(repeat_records)) for record in repeat_records: self.assertEqual(case_id, record.payload_id) # update case and run checks post_case_blocks([ CaseBlock.deprecated_init( create=False, case_id=case_id, ).as_xml() ], domain=self.domain) repeat_records = list( RepeatRecord.all(domain=self.domain, due_before=later)) self.assertEqual(expected_records_after_update, len(repeat_records)) for record in repeat_records: self.assertEqual(case_id, record.payload_id)
def test_process_repeat_record_locking(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.motech.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2) with patch('corehq.motech.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.motech.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.motech.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 2) with patch('corehq.motech.repeaters.models.simple_post') 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 _run_test(self, event_type, expected_records_after_create, expected_records_after_update, case_type=ZAPIER_CASE_TYPE): ZapierSubscription.objects.create( domain=self.domain, user_id=str(self.web_user._id), event_name=event_type, url='http://example.com/lets-make-some-cases/', case_type=ZAPIER_CASE_TYPE, ) # create case and run checks case_id = uuid.uuid4().hex post_case_blocks( [ CaseBlock( create=True, case_id=case_id, case_type=case_type, ).as_xml() ], domain=self.domain ) # Enqueued repeat records have next_check set 48 hours in the future. later = datetime.utcnow() + timedelta(hours=48 + 1) repeat_records = list(RepeatRecord.all(domain=self.domain, due_before=later)) self.assertEqual(expected_records_after_create, len(repeat_records)) for record in repeat_records: self.assertEqual(case_id, record.payload_id) # update case and run checks post_case_blocks( [ CaseBlock( create=False, case_id=case_id, ).as_xml() ], domain=self.domain ) repeat_records = list(RepeatRecord.all(domain=self.domain, due_before=later)) self.assertEqual(expected_records_after_update, len(repeat_records)) for record in repeat_records: self.assertEqual(case_id, record.payload_id)
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_repeat_record_not_created(self): """ When an application without a repeater is saved, then a repeat record should not be created """ self.application = Application(domain=self.domain) self.application.save() self.addCleanup(self.application.delete) # Enqueued repeat records have next_check set 48 hours in the future. later = datetime.utcnow() + timedelta(hours=48 + 1) repeat_records = RepeatRecord.all(domain=self.domain, due_before=later) self.assertEqual(len(repeat_records), 0)
def _run_test(self, event_type, expected_records_after_create, expected_records_after_update, case_type=ZAPIER_CASE_TYPE): ZapierSubscription.objects.create( domain=self.domain, user_id=str(self.web_user._id), event_name=event_type, url='http://example.com/lets-make-some-cases/', case_type=ZAPIER_CASE_TYPE, ) # create case and run checks case_id = uuid.uuid4().hex post_case_blocks( [ CaseBlock( create=True, case_id=case_id, case_type=case_type, ).as_xml() ], domain=self.domain ) repeat_records = list(RepeatRecord.all(domain=self.domain)) self.assertEqual(expected_records_after_create, len(repeat_records)) for record in repeat_records: self.assertEqual(case_id, record.payload_id) # update case and run checks post_case_blocks( [ CaseBlock( create=False, case_id=case_id, ).as_xml() ], domain=self.domain ) repeat_records = list(RepeatRecord.all(domain=self.domain)) self.assertEqual(expected_records_after_update, len(repeat_records)) for record in repeat_records: self.assertEqual(case_id, record.payload_id)
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.motech.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(), verify=repeat_record.repeater.verify, ) # The following is pretty fickle and depends on which of # - corehq.motech.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_repeater_successful_send(self): repeat_records = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) for repeat_record in repeat_records: with patch( 'corehq.motech.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(), verify=repeat_record.repeater.verify, ) # The following is pretty fickle and depends on which of # - corehq.motech.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_created(self): """ When an application with a repeater is saved, then a repeat record should be created """ self.app_structure_repeater = AppStructureRepeater(domain=self.domain, url=self.forwarding_url) self.app_structure_repeater.save() self.addCleanup(self.app_structure_repeater.delete) self.application = Application(domain=self.domain) self.application.save() self.addCleanup(self.application.delete) later = datetime.utcnow() + timedelta(hours=48 + 1) repeat_records = RepeatRecord.all(domain=self.domain, due_before=later) self.assertEqual(len(repeat_records), 1)
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.repeater.get_url(repeat_record), self.forwarding_url) self.assertEqual(repeat_record.get_payload(), application.get_id) repeat_record.delete() application.delete() app_structure_repeater.delete()
def cleanup_repeat_records_for_domain(domain): for repeat_record in RepeatRecord.all(domain=domain): repeat_record.delete()
def repeat_records(self): return RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow())
def repeat_records(self): # Enqueued repeat records have next_check set 48 hours in the future. later = datetime.utcnow() + timedelta(hours=48 + 1) return RepeatRecord.all(domain=self.domain, due_before=later)
def repeat_records(cls, domain_name): return RepeatRecord.all(domain=domain_name, due_before=datetime.utcnow())