class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument( 'domain', help="File path for log file", ) parser.add_argument( 'log_file', help="File path for log file", ) def handle(self, domain, log_file, **options): total_cases = CaseES().domain(domain).case_type('household').is_closed().count() self.case_accessor = CaseAccessors(domain) failed_updates = [] with open(log_file, "w", encoding='utf-8') as fh: fh.write('--------Successful Form Ids----------\n') for cases in chunked(with_progress_bar(self._get_cases_to_process(domain), total_cases), 100): related_cases = self._get_related_cases(cases) case_tupes = [(case_id, {}, True) for case_id in related_cases] try: xform, cases = bulk_update_cases( domain, case_tupes, self.__module__) fh.write(xform.form_id + '\n') except LocalSubmissionError as e: print('submission error') print(six.text_type(e)) failed_updates.extend(related_cases) except Exception as e: print('unexpected error') print(six.text_type(e)) failed_updates.extend(related_cases) fh.write('--------Failed Cases--------------\n') for case_id in failed_updates: fh.write(case_id) print('-------------COMPLETE--------------') def _get_cases_to_process(self, domain): from corehq.sql_db.util import get_db_aliases_for_partitioned_query dbs = get_db_aliases_for_partitioned_query() for db in dbs: cases = CommCareCaseSQL.objects.using(db).filter(domain=domain, type='household', closed=True) for case in cases: yield case.case_id def _get_related_cases(self, cases): related_cases = {case.case_id for case in self.case_accessor.get_all_reverse_indices_info(list(cases)) if case.relationship == CommCareCaseIndexSQL.CHILD} related_cases |= {case.case_id for case in self.case_accessor.get_all_reverse_indices_info(list(related_cases)) if case.relationship == CommCareCaseIndexSQL.CHILD} return related_cases
def get_cleanliness_flag_from_scratch(domain, owner_id): casedb = CaseAccessors(domain) footprint_info = get_case_footprint_info(domain, owner_id) owned_cases = footprint_info.base_ids cases_to_check = footprint_info.all_ids - owned_cases if cases_to_check: closed_owned_case_ids = set(casedb.get_closed_case_ids_for_owner(owner_id)) cases_to_check = cases_to_check - closed_owned_case_ids - footprint_info.extension_ids # check extension cases that are unowned or owned by others extension_cases_to_check = footprint_info.extension_ids - closed_owned_case_ids - owned_cases while extension_cases_to_check: extension_case = extension_cases_to_check.pop() dependent_cases = set(get_dependent_case_info(domain, [extension_case]).all_ids) unowned_dependent_cases = dependent_cases - owned_cases extension_cases_to_check = extension_cases_to_check - dependent_cases dependent_cases_owned_by_other_owners = { dependent_case.case_id for dependent_case in casedb.get_cases(list(unowned_dependent_cases)) if dependent_case.owner_id != UNOWNED_EXTENSION_OWNER_ID } if dependent_cases_owned_by_other_owners: hint_id = dependent_cases & owned_cases # can't get back from extension case to owned case e.g. host is a child of owned case if hint_id: return CleanlinessFlag(False, hint_id.pop()) if cases_to_check: # it wasn't in any of the open or closed IDs - it must be dirty reverse_index_infos = casedb.get_all_reverse_indices_info(list(cases_to_check)) reverse_index_ids = set([r.case_id for r in reverse_index_infos]) indexed_with_right_owner = (reverse_index_ids & (owned_cases | closed_owned_case_ids)) found_deleted_cases = False while indexed_with_right_owner: hint_id = indexed_with_right_owner.pop() infos_for_this_owner = _get_info_by_case_id(reverse_index_infos, hint_id) for info in infos_for_this_owner: try: case = CaseAccessors(domain).get_case(info.referenced_id) if not case.is_deleted: return CleanlinessFlag(False, hint_id) else: found_deleted_cases = True except ResourceNotFound: # the case doesn't exist - don't use it as a dirty flag found_deleted_cases = True if found_deleted_cases: # if we made it all the way to the end of the loop without returning anything # then the owner was only flagged as dirty due to missing cases, # This implies the owner is still clean. return CleanlinessFlag(True, None) else: # I don't believe code can ever be hit, but if it is we should fail hard # until we can better understand it. raise IllegalCaseId('Owner {} in domain {} has an invalid index reference chain!!'.format( owner_id, domain )) return CleanlinessFlag(True, None)
def get_cleanliness_flag_from_scratch(domain, owner_id): casedb = CaseAccessors(domain) footprint_info = get_case_footprint_info(domain, owner_id) owned_cases = footprint_info.base_ids cases_to_check = footprint_info.all_ids - owned_cases if cases_to_check: closed_owned_case_ids = set(casedb.get_closed_case_ids_for_owner(owner_id)) cases_to_check = cases_to_check - closed_owned_case_ids - footprint_info.extension_ids # check extension cases that are unowned or owned by others extension_cases_to_check = footprint_info.extension_ids - closed_owned_case_ids - owned_cases while extension_cases_to_check: extension_case = extension_cases_to_check.pop() dependent_cases = set(get_dependent_case_info(domain, [extension_case]).all_ids) unowned_dependent_cases = dependent_cases - owned_cases extension_cases_to_check = extension_cases_to_check - dependent_cases dependent_cases_owned_by_other_owners = { dependent_case.case_id for dependent_case in casedb.get_cases(list(unowned_dependent_cases)) if dependent_case.owner_id != UNOWNED_EXTENSION_OWNER_ID } if dependent_cases_owned_by_other_owners: hint_id = dependent_cases & owned_cases # can't get back from extension case to owned case e.g. host is a child of owned case if hint_id: return CleanlinessFlag(False, hint_id.pop()) if cases_to_check: # it wasn't in any of the open or closed IDs - it must be dirty reverse_index_infos = casedb.get_all_reverse_indices_info(list(cases_to_check)) reverse_index_ids = set([r.case_id for r in reverse_index_infos]) indexed_with_right_owner = (reverse_index_ids & (owned_cases | closed_owned_case_ids)) found_deleted_cases = False while indexed_with_right_owner: hint_id = indexed_with_right_owner.pop() infos_for_this_owner = _get_info_by_case_id(reverse_index_infos, hint_id) for info in infos_for_this_owner: try: case = CaseAccessors(domain).get_case(info.referenced_id) if not case.is_deleted: return CleanlinessFlag(False, hint_id) else: found_deleted_cases = True except ResourceNotFound: # the case doesn't exist - don't use it as a dirty flag found_deleted_cases = True if found_deleted_cases: # if we made it all the way to the end of the loop without returning anything # then the owner was only flagged as dirty due to missing cases, # This implies the owner is still clean. return CleanlinessFlag(True, None) else: # I don't believe code can ever be hit, but if it is we should fail hard # until we can better understand it. raise IllegalCaseId('Owner {} in domain {} has an invalid index reference chain!!'.format( owner_id, domain ))
class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument( 'domain', help="File path for log file", ) parser.add_argument( 'log_file', help="File path for log file", ) def handle(self, domain, log_file, **options): total_cases = CaseES().domain(domain).case_type( 'household').is_closed().count() self.case_accessor = CaseAccessors(domain) failed_updates = [] with open(log_file, "w", encoding='utf-8') as fh: fh.write('--------Successful Form Ids----------\n') for cases in chunked( with_progress_bar(self._get_cases_to_process(domain), total_cases), 100): related_cases = self._get_related_cases(cases) case_tupes = [(case_id, {}, True) for case_id in related_cases] try: xform, cases = bulk_update_cases(domain, case_tupes, self.__module__) fh.write(xform.form_id + '\n') except LocalSubmissionError as e: print('submission error') print(six.text_type(e)) failed_updates.extend(related_cases) except Exception as e: print('unexpected error') print(six.text_type(e)) failed_updates.extend(related_cases) fh.write('--------Failed Cases--------------\n') for case_id in failed_updates: fh.write(case_id) print('-------------COMPLETE--------------') def _get_cases_to_process(self, domain): from corehq.sql_db.util import get_db_aliases_for_partitioned_query dbs = get_db_aliases_for_partitioned_query() for db in dbs: cases = CommCareCaseSQL.objects.using(db).filter(domain=domain, type='household', closed=True) for case in cases: yield case.case_id def _get_related_cases(self, cases): related_cases = { case.case_id for case in self.case_accessor.get_all_reverse_indices_info( list(cases)) if case.relationship == CommCareCaseIndexSQL.CHILD }